目录
今天实现一个带头双向循环链表。
前面我们学习了单链表。但是链表并不仅限只有【单链表】。【链表】是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

单向或者双向

带头或者不带头

循环或者非循环

这些特征组合起来可以构成:8种形态的链表。

虽然有这么多的链表的结构,但是我们实际中最常用的还是有两种结构。
【无头单项非循环链表】&【带头双向循环链表】

- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。实际生活中使用很多。
在前面我们已经学过 无头单项不循环链表,这里我们来实现 带头双向循环链表

- int main()
- {
- LTNode* phead = LTInit();//初始化
- test1(phead);//头插
- test2(phead);//头删
- test3(phead);//尾插
- test4(phead);//尾删
- test5(phead);//查询某个数字
-
- test6(phead);//插入pos位置的前一个/后一个元素
- test7(phead);//删除pos位置的元素
- LTDestroy(phead);//空间释放/防止内存泄露
- return 0;
- }
- #include"DList.h"
- void test1(LTNode* phead)//头插
- {
- LTPushFront(phead, 7);
- LTPushFront(phead, 3);
- LTPushFront(phead, 4);
- LTPushFront(phead, 7);
- LTPushFront(phead, 8);
- LTPushFront(phead, 9);
- LTPrint(phead);
- }
- void test2(LTNode* phead)//头删
- {
- LTPopFront(phead);
- LTPopFront(phead);
- LTPopFront(phead);
- LTPrint(phead);
- }
- void test3(LTNode* phead)//尾插
- {
- LTPushBack(phead, 77);
- LTPushBack(phead, 99);
- LTPrint(phead);
- }
- void test4(LTNode* phead)//尾删
- {
- LTPopBack(phead);
- LTPopBack(phead);
- LTPopBack(phead);
- LTPopBack(phead);
- LTPrint(phead);
- }
- void test5(LTNode* phead)//查询
- {
- LTNode* node = LTFind(phead, 4);
- if (node == NULL)
- {
- printf("没找到");
- }
- else
- {
- printf("%d", node->val);
- }
- }
- void test6(LTNode* phead)//插入pos位置的前一个/后一个元素
- {
- LTNode* pos = LTFind(phead, 4);
- LTInsertAfter(phead, pos, 77);
- LTInsertAfter(phead, pos, 66);
- LTInsertAfter(phead, pos, 99);
- LTPrint(phead);
- }
- //删除pos位置的元素
- void test7(LTNode* phead)
- {
- LTNode* pos = LTFind(phead, 4);
- if(pos)//查询成功才进入
- {
- LTErase(phead, pos);
- pos=NULL;
- }
- LTPrint(phead);
- }
- #include"DList.h"
- void test1(LTNode* phead)//头插
- {
- LTPushFront(phead, 7);
- LTPushFront(phead, 3);
- LTPushFront(phead, 4);
- LTPushFront(phead, 7);
- LTPushFront(phead, 8);
- LTPushFront(phead, 9);
- LTPrint(phead);
- }
-
- void test2(LTNode* phead)//头删
- {
- LTPopFront(phead);
- LTPopFront(phead);
- LTPopFront(phead);
- LTPrint(phead);
- }
-
- void test3(LTNode* phead)//尾插
- {
- LTPushBack(phead, 77);
- LTPushBack(phead, 99);
- LTPrint(phead);
- }
-
- void test4(LTNode* phead)//尾删
- {
- LTPopBack(phead);
- LTPopBack(phead);
- LTPopBack(phead);
- LTPopBack(phead);
- LTPrint(phead);
- }
-
- void test5(LTNode* phead)//查询
- {
- LTNode* node = LTFind(phead, 4);
- if (node == NULL)
- {
- printf("没找到");
- }
- else
- {
- printf("%d", node->val);
- }
- }
-
- void test6(LTNode* phead)//插入pos位置的前一个/后一个元素
- {
- LTNode* pos = LTFind(phead, 4);
- LTInsertAfter(phead, pos, 77);
- LTInsertAfter(phead, pos, 66);
- LTInsertAfter(phead, pos, 99);
- LTPrint(phead);
- }
-
- //删除pos位置的元素
- void test7(LTNode* phead)
- {
- LTNode* pos = LTFind(phead, 4);
- if(pos)//查询成功才进入
- {
- LTErase(phead, pos);
- pos=NULL;
- }
- LTPrint(phead);
- }
-
-
- int main()
- {
- LTNode* phead = LTInit();//已经被初始化了
- test1(phead);//头插
- test2(phead);//头删
- test3(phead);//尾插
- test4(phead);//尾删
- test5(phead);//查询某个数字
-
- test6(phead);//插入pos位置的前一个/后一个元素
- test7(phead);//删除pos位置的元素
- LTDestroy(phead);//空间释放/防止内存泄露
- phead=NULL;
- return 0;
- }
- #pragma once
- #include
- #include
- #include
- assert(//)//括号里是可以出现的情况为真 若括号里的表达式为假那就❌
- typedef int LTDateType;
- //声明节点
- typedef struct DListNode
- {
- LTDateType val;
- struct DListNode* prev;
- struct DListNode* next;
- }LTNode;
LTNode* LTInit();
void LTPushFront(LTNode*phead, LTDateType x);
void LTPopFront(LTNode* phead);
void LTPushBack(LTNode* phead,LTDateType x);
void LTPopBack(LTNode* phead);
void LTPrint(LTNode* phead);
LTNode* LTFind(LTNode* phead);
void LTInsertAfter(LTNode* phead, LTNode* pos, LTDateType x);
void LTErase(LTNode* phead, LTNode* pos);
void LTDestroy(LTNode* phead);
- #pragma once
- #include
- #include
- #include
-
- typedef int LTDateType;
-
- //定义节点
- typedef struct DListNode
- {
- LTDateType val;
- struct DListNode* prev;
- struct DListNode* next;
- }LTNode;
-
- //初始化
- LTNode* LTInit();//不用二级指针/用返回值改变实参
- void LTPushFront(LTNode*phead, LTDateType x);//头插
- void LTPopFront(LTNode* phead);//头删
- void LTPushBack(LTNode* phead,LTDateType x);//尾插
- void LTPopBack(LTNode* phead);//尾删
- void LTPrint(LTNode* phead);//打印
- LTNode* LTFind(LTNode* phead);//查询
- void LTInsertAfter(LTNode* phead, LTNode* pos, LTDateType x);//在pos的后面插入一个元素
- void LTErase(LTNode* phead, LTNode* pos);//删除pos位置的元素
- void LTDestroy(LTNode* phead);//销毁释放
-
- //初始化
- LTNode* LTInit()
- {
- LTNode* phead = Createnode(-1);
- phead->prev = phead;
- phead->next = phead;
- return phead;
- }
- #include"DList.h"
- //创造节点
- LTNode* Createnode(LTDateType x)
- {
- LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
- if (newnode == NULL)
- {
- perror("malloc");
- exit(-1);//程序停止
- }
- newnode->val = x;
- newnode->prev = NULL;
- newnode->next = NULL;
- return newnode;
- }
- //初始化
- LTNode* LTInit()
- {
- LTNode* phead = Createnode(-1);
- phead->prev = phead;
- phead->next = phead;
- return phead;
- }
- //打印
- void LTPrint(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead;
- printf("<=>");
- printf("%d<=>", cur->val);
- cur = cur->next;
- while (cur != phead)
- {
- printf("%d<=>", cur->val);
- cur = cur->next;
- }
- printf("\n");
- }
- //头插
- void LTPushFront(LTNode* phead,LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->next = phead->next;
- phead->next->prev = newnode;
- phead->next = newnode;
- newnode->prev = phead;
- }

- //头删
- void LTPopFront(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead->next;
- LTNode* next = cur->next;
- assert(cur != phead); //考虑如果链表为NULL
- phead->next = next;
- next->prev = phead;
- free(cur);
- cur = NULL;
- }
- //尾插
- void LTPushBack(LTNode* phead, LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->prev = phead->prev;
- phead->prev->next = newnode;
- newnode->next = phead;
- phead->prev = newnode;
- }
- //尾删
- void LTPopBack(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead->prev;
- LTNode* next = cur->prev;
- assert(cur != phead);
- phead->prev = next;
- next->next = phead;
- free(cur);
- cur = NULL;
- }
- //查询
- //查询某个数,存在返回节点地址,不存在返回NULL
- LTNode* LTFind(LTNode* phead, LTDateType x)
- {
- assert(phead);
- LTNode* cur = phead->next;
- while (cur != phead)
- {
- if (cur->val == x)
- {
- return cur;
- }
- cur = cur->next;
- }
- return NULL;
- }
- //在pos的后面插入一个元素
- void LTInsertAfter(LTNode* phead, LTNode*pos, LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->next = pos->next;
- pos->next->prev = newnode;
- pos->next = newnode;
- newno
- //删除pos位置的元素//
- void LTErase(LTNode* phead, LTNode* pos)
- {
- assert(phead);
- assert(phead->next != phead);
- LTNode* cur = pos->prev;
- LTNode* next = pos->next;
- cur->next = next;
- next->prev = cur;
- free(pos);
- pos = NULL;
- }
- //销毁
- void LTDestroy(LTNode* phead)
- {
- assert(phead);
- assert(phead->next != phead);
- LTNode* cur = phead->next;
- while (cur != phead)
- {
- LTNode* tmp = cur->next;
- free(cur);
- cur = tmp;
- }
- }
- #include"DList.h"
- //创造节点
- LTNode* Createnode(LTDateType x)
- {
- LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
- if (newnode == NULL)
- {
- perror("malloc");
- exit(-1);//程序停止
- }
- newnode->val = x;
- newnode->prev = NULL;
- newnode->next = NULL;
- return newnode;
- }
- //初始化
- LTNode* LTInit()
- {
- LTNode* phead = Createnode(-1);
- phead->prev = phead;
- phead->next = phead;
- return phead;
- }
- //打印
- void LTPrint(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead;
- printf("<=>");
- printf("%d<=>", cur->val);
- cur = cur->next;
- while (cur != phead)
- {
- printf("%d<=>", cur->val);
- cur = cur->next;
- }
- printf("\n");
- }
- //头插
- void LTPushFront(LTNode* phead,LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->next = phead->next;
- phead->next->prev = newnode;
- phead->next = newnode;
- newnode->prev = phead;
- }
- //头删
- void LTPopFront(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead->next;
- LTNode* next = cur->next;
- assert(cur != phead); //考虑如果链表为NULL
- phead->next = next;
- next->prev = phead;
- free(cur);
- cur = NULL;
- }
- //尾插
- void LTPushBack(LTNode* phead, LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->prev = phead->prev;
- phead->prev->next = newnode;
- newnode->next = phead;
- phead->prev = newnode;
- }
- //尾删
- void LTPopBack(LTNode* phead)
- {
- assert(phead);
- LTNode* cur = phead->prev;
- LTNode* next = cur->prev;
- assert(cur != phead);
- phead->prev = next;
- next->next = phead;
- free(cur);
- cur = NULL;
- }
- //查询
- //查询某个数,存在返回节点地址,不存在返回NULL
- LTNode* LTFind(LTNode* phead, LTDateType x)
- {
- assert(phead);
- LTNode* cur = phead->next;
- while (cur != phead)
- {
- if (cur->val == x)
- {
- return cur;
- }
- cur = cur->next;
- }
- return NULL;
- }
- //在pos的后面插入一个元素
- void LTInsertAfter(LTNode* phead, LTNode*pos, LTDateType x)
- {
- assert(phead);
- LTNode* newnode = Createnode(x);
- newnode->next = pos->next;
- pos->next->prev = newnode;
- pos->next = newnode;
- newnode->prev = pos;
- }
- //删除pos位置的元素//
- void LTErase(LTNode* phead, LTNode* pos)
- {
- assert(phead);
- assert(phead->next != phead);
- LTNode* cur = pos->prev;
- LTNode* next = pos->next;
- cur->next = next;
- next->prev = cur;
- free(pos);
- pos = NULL;
- }
- //销毁
- void LTDestroy(LTNode* phead)
- {
- assert(phead);
- assert(phead->next != phead);
- LTNode* cur = phead->next;
- while (cur != phead)
- {
- LTNode* tmp = cur->next;
- free(cur);
- cur = tmp;
- }
- cur=NULL;
- }
- //形式参数这里就可以置NULL
- //实际参数到主函数里面置NULL
-
-

✔✔✔✔✔最后感谢大家的阅读,若有错误和不足,欢迎指正!乖乖敲代码哦!
代码---------→【唐棣棣 (TSQXG) - Gitee.com】
联系---------→【邮箱:2784139418@qq.com】