目录

1.什么是双向带头循环链表?模型。

2.1 创建结点函数

2.2初始化

3.尾插实现

3.1图示

3.2尾插

4.打印函数实现

4.1打印函数

5.思考为啥是一级指针

6.头插实现

6.2实现代码

6.3特殊情况

7.头删

7.1图解

7.2代码

7.3多删

8.尾删

8.1上图

8.2代码

9.在任意(pos)位置的插入删除。

9.1 插入

9.2尾插·头插的复用

9.3思考

9.4pos位置的删除

9.6思考

10销毁

11.SList.h代码

12.SList.c代码


1.什么是双向带头循环链表?模型。

上次写的链表是单向的,就是只去不会,但是我想让他有来有回所以叫单向,带头是创建一个哨兵位头结点,但不影响实际写的链表。循环我就不解释了。

上模型:

2.初始化链表

2.1 创建结点函数

ListNode* BuyListNode(SLTDateType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));  //开辟一个结点if (node == NULL){perror("malloc:fault");exit(-1);}node->date = x;      //把值给这个结点node->next = NULL;   //   全都赋值node->prev = NULL;    //全都赋值return  node;
}

2.2初始化

//初始化
ListNode* ListInit()
{ListNode* phead = BuyListNode(-1);  //创建哨兵位,不一定取-1,想取啥取啥phead->next = phead;phead->prev = phead;//既然是循环,那它的头指向自己,尾指向自己return phead;
}

刚开始就一个头结点,所以要首尾都指向自身。

3.尾插实现

3.1图示

3.2尾插

//尾插
void ListPushBack(ListNode* phead, SLTDateType x)
{assert(phead);ListNode* newnode = BuyListNode(x);ListNode* tail = phead->prev;tail->next = newnode;  //把newnode给tailnewnode->prev = tail;newnode->next = phead;phead->prev = newnode;
}

最灵性的的是tail=phead->prev,所以首尾相连了。

要实现尾插,无非四步d3结点和newnode相连,phead和newnode相连。

4.打印函数实现

4.1打印函数

//打印函数
void ListPrint(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->date);cur = cur->next;}printf("\n");
}

注意不打印头结点所以cur是phead->next; 判断条件是!=phead,因为这是一个循环,最后一个跟phead连着呢,所以不等于。

4.2尾插实现

5.思考为啥是一级指针

单链表是二级指针实现尾插的,为啥这个是一级指针?为啥能用一级指针?

当我们写单链表时,要实现尾插首先我们要找到尾,咱们一般都是定义一个一级指针并改变这个指针来找尾,但是循环链表就不需要了。因为它的尾和phead紧密相连(设cur是尾),cur->next就是头,所以不需要一级指针的改变,所以一级指针就可以应付了。

6.头插实现

6.1图解

是插在d1前面不是head前面。

6.2实现代码

//头插
void ListPushFront(ListNode* phead, SLTDateType x)
{assert(phead);ListNode* newnode = BuyListNode(x);ListNode* next = phead->next;   //来记录d1的地址放止一会找不到。//还是四步链接phead->next = newnode;newnode->prev = phead;newnode->next=next;next->prev=newnode;
}

注意:其实不加这个next也可以,为啥还要加,就看上面这个代码,如果先连接phead和newnode那d1的地址咱就找不到了,所以就只能先连接后边的,但是加上next就不用看顺序来

了。

6.3特殊情况

就只有一个头结点进行头插,那next就是phead了。

再看咱这代码加图,照样可以。把d1换成phead,一样。

7.头删

7.1图解

注意啊兄弟们,不是删除第一个,第一个是哨兵节点,d1才是实际上的第一个。

7.2代码

//头删
void ListPopFront(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;phead->next = cur->next;cur->next->prev = phead;free(cur);}

cur->next是d2,把d2的地址给phead,所以是cur->next->prev。

7.3多删

如果五个数据删六次呢?

所以代码:

//头删
void ListPopFront(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* cur = phead->next;phead->next = cur->next;cur->next->prev = phead;free(cur);}

8.尾删

8.1上图

双链表对尾删最友好的地方是不用遍历找尾,phead->prev就是尾。

8.2代码

//尾删
void ListPopBack(ListNode* phead)
{assert(phead);assert(phead->next != phead); //前车之鉴ListNode* tail = phead->prev;ListNode* tailPrev = tail->prev;free(tail);tailPrev->next = phead;phead->prev = tailPrev;
}

9.在任意(pos)位置的插入删除。

9.1 插入

//pos位置插
void ListInsert(ListNode* pos, SLTDateType x)
{   assert(pos);ListNode* prev = pos->prev;   //pos前面的那个结点ListNode* newnode = BuyListNode(x);//四步走prev->next=newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}

9.2尾插·头插的复用

9.3思考

为啥尾插是参数phead?

d3是尾,要在d3那插入可不是尾插,在phead前插入不就是尾插吗?因为phead->prev必须指向链表的尾部。

9.4pos位置的删除

9.5复用

9.6思考

为啥尾插是phead,而尾删是phead->prev?

首先我们要理解进行尾插时,就是在pos前插入,那要找到pos位置,并在它前边插入,pos就是phead。

而进行尾删时也要找到pos,并删除pos,这个是删除pos位。所以是phead->prev。

10销毁

//销毁
void ListDestory(ListNode* phead)
{ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);
}

11.SList.h代码

#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>typedef int SLTDateType;typedef struct ListNode
{struct ListNode* prev;     //头struct ListNode* next;     //尾SLTDateType  date;
}ListNode;//初始化
ListNode* ListInit();//打印
void ListPrint(ListNode* phead);//开辟节点
ListNode* BuyListNode(SLTDateType x);//尾插
void ListPushBack(ListNode* phead, SLTDateType x);//头插
void ListPushFront(ListNode* phead, SLTDateType x);//头删
void ListPopFront(ListNode* phead);//尾删
void ListPopBack(ListNode* phead);//pos位置插
void ListInsert(ListNode* pos, SLTDateType x);//pos位置删除
void ListErase(ListNode* pos);//销毁
void ListDestory(ListNode* phead);

12.SList.c代码

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"ListNode* BuyListNode(SLTDateType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));  //开辟一个结点if (node == NULL){perror("malloc:fault");exit(-1);}node->date = x;      //把值给这个结点node->next = NULL;   //   全都赋值node->prev = NULL;    //全都赋值return  node;
}
//初始化
ListNode* ListInit()
{ListNode* phead = BuyListNode(-1);  //创建哨兵位,不一定取-1,想取啥取啥phead->next = phead;phead->prev = phead;//既然是循环,那它的头指向自己,尾指向自己return phead;
}//打印函数
void ListPrint(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->date);cur = cur->next;}printf("\n");
}//尾插
void ListPushBack(ListNode* phead, SLTDateType x)
{assert(phead);ListInsert(phead, x);//ListNode* newnode = BuyListNode(x);//ListNode* tail = phead->prev;//tail->next = newnode;  //把newnode给tail//newnode->prev = tail;//newnode->next = phead;//phead->prev = newnode;
}//头插
void ListPushFront(ListNode* phead, SLTDateType x)
{assert(phead);ListInsert(phead->next, x);//ListNode* newnode = BuyListNode(x);//ListNode* next = phead->next;   //来记录d1的地址放止一会找不到。//还是四步链接//phead->next = newnode;//newnode->prev = phead;//newnode->next=next;//next->prev=newnode;
}//头删
void ListPopFront(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListErase(phead->next);/*ListNode* cur = phead->next;phead->next = cur->next;cur->next->prev = phead;free(cur);*/}//尾删
void ListPopBack(ListNode* phead)
{assert(phead);assert(phead->next != phead); //前车之鉴ListErase(phead->prev);/*ListNode* tail = phead->prev;ListNode* tailPrev = tail->prev;free(tail);tailPrev->next = phead;phead->prev = tailPrev;*/
}//pos位置插
void ListInsert(ListNode* pos, SLTDateType x)
{   assert(pos);ListNode* prev = pos->prev;   //pos前面的那个结点ListNode* newnode = BuyListNode(x);//四步走prev->next=newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}//pos位置删除
void ListErase(ListNode* pos)
{ListNode* prev = pos->prev;ListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);
}//销毁
void ListDestory(ListNode* phead)
{ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);
}

数据结构------双向带头循环链表相关推荐

  1. 【数据结构--双向带头循环链表(链表中的老大哥)】

    双向带头循环链表及相关OJ

  2. 【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单

    目录 0.结构体定义 1.初始化 2.尾插 3.打印 4.头插 5.任意位置插入前面位置 6.尾删 7.头删 8.链表长度 9.任意位置删除当前位置 10. 销毁 双向带头循环链表:结构复杂,操作简单 ...

  3. 链表界的“扛把子”—双向带头循环链表

    目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...

  4. 双向带头循环链表的实现

    双向带头循环链表 双向带头循环链表 结构讲解 期望实现功能 创建链表和头节点作用 头插和头删 头插 头删 尾插与尾删 尾插 尾删 pos 删除和插入 插入 删除 打印和查找 整体代码 这个数据结构可以 ...

  5. 【双向带头循环链表】

    双向带头循环链表 0.链表中每个节点的基本结构 1.初始化链表(创建哨兵位头节点) 2.申请新节点 3.尾插节点 4.尾删节点 5.头插节点 6.头删节点 7.寻找pos位置的节点 8.在pos位置之 ...

  6. 双向带头循环链表-实现思路+图解

    目录 一.何为双向循环链表? 1.何为'双向'? 2.何为'带头'? 3.何为'循环'? 二.如何实现双向带头循环链表? 1.基本结构-结点的创建 2.创建哨兵位结点 3.链表的增删查改 一.何为双向 ...

  7. 双向带头循环链表的(增删查改)的实现

    文章目录 一.双向带头循环链表 构成 二.双向带头循环链表的实现 1.函数的定义和结构体的创建--list.h 2.函数的调用--list.c 3. 双向带头循环链表与单链表的传递参数区别 4.双向带 ...

  8. 外强中干——双向带头循环链表

    前言:众所周知,链表有八种结构,由单向或双向,有头或无头,循环或不循环构成.在本篇,将介绍8种链表结构中最复杂的--双向带头循环链表.听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单 ...

  9. 双向带头循环链表详解

    在上一篇所讲述的 单链表 中,存在一些缺陷: 1.在进行尾插和尾删时,需要遍历链表找到尾结点 2.在进行中间插入和删除时,也需要先遍历链表找到前一个结点 对于这些缺陷,可以采用一种结构更为复杂的链表 ...

最新文章

  1. DrawerLayout侧滑详解
  2. profile之springboot
  3. ubuntu20.04安装edge浏览器
  4. Dom4j SAXReader Constructors
  5. 高级工程师java_Java从0到高级工程师
  6. 一段获取视频的简易方法
  7. 学习自己动手设计数据库
  8. 前端需要学python吗_python是前端语言吗
  9. 国密算法和GmSSL介绍
  10. “黑客帝国”装B特效,不分linux版本
  11. Web App - MUI框架初体验
  12. linux scp命令,linux中scp命令和scp命令用法大全
  13. 4-9 Python对象的自省机制
  14. 十个值得所有极客收藏的网站
  15. 《生活中的魔法数学》读后感
  16. Docker存储驱动之Btrfs简介
  17. 林亦杉厦门大学计算机学院,挥别厦大,点燃未来-厦门大学计算机科学系
  18. 华为在HDC2021发布全新HMS Core 6 宣布跨OS能力开放
  19. element方法的自定义参数传参方式
  20. 解压报错 你需要从上一压缩卷启动解压命令以便解压 解决方案及WinRAR怎么分卷压缩详解

热门文章

  1. clock gating门控时钟
  2. Clock Gating cell 与 Integrated Clock Gating cell(ICG)
  3. Neo4j apoc cycles(一)
  4. Neo4j Desktop通过apoc 导入json文件
  5. 衡水数控ug编程加工中心机床模具培寻
  6. 【OpenCV-Python】教程:8-3 高动态范围 HDR
  7. html中main标签什么意思,html5main标签是什么意思?html5main标签作用的详细介绍-
  8. 开源英雄坛说操作修改版
  9. HUAWEI-ECS常用运维工具(干)
  10. xcode清理缓存_腾讯柠檬清理,真的比 CleanMyMac 好用么?