网站的 营销渠道的建设,做暖暖视频免费观看免费网站,网站seo优化效果,哪里可以学seo课程详解C语言动态实现带头结点的双向循环链表结构~#x1f60e;前言#x1f64c;预备小知识#x1f49e;链表的概念及结构#x1f64c;预备小知识#x1f49e;链表的概念及结构#x1f64c;带头结点的双向循环链表结构#x1f64c;整体实现内容分析#x1f49e;1.头文件编…
详解C语言动态实现带头结点的双向循环链表结构~前言预备小知识链表的概念及结构预备小知识链表的概念及结构带头结点的双向循环链表结构整体实现内容分析1.头文件编码实现2.代码功能实现1这是生成新节点函数实现。2)生成带头结点的空链表函数实现。3)删除链表函数实现。4)顺序输出链表函数实现。5)尾插函数实现。6头插函数实现。7头删函数实现。8尾删函数的实现。9查找函数实现。10pos位置之前插入x的函数实现。11删除pos位置的值的函数实现。12逆序输出的函数实现。13判空函数实现。3.测试文件源码分享总结撒花博客昵称博客小梦 最喜欢的座右铭全神贯注的上吧 作者简介一名热爱C/C算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主 博主小留言哈喽各位CSDN的uu们我是你的博客好友小梦希望我的文章可以给您带来一定的帮助话不多说文章推上欢迎大家在评论区唠嗑指正觉得好的话别忘了一键三连哦 前言 哈喽各位友友们我今天又学到了很多有趣的知识现在迫不及待的想和大家分享一下我仅已此文手把手带领大家学习C语言动态实现实现带头结点的双向循环链表结构~ 用代码来实现一个带头结点的双向循环链表结构完成增删查改顺序输出和逆序输出判空的功能。都是精华内容可不要错过哟 预备小知识
链表的概念及结构
链表是一种物理存储结构上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链 接次序实现的 。
预备小知识
链表的概念及结构
链表是一种物理存储结构上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链 接次序实现的 。 带头结点的双向循环链表结构
带头双向循环链表结构最复杂一般用在单独存储数据。实际中使用的链表数据结构都是带头双向循环链表。另外这个结构虽然结构复杂但是使用代码实现以后会发现结构会带来很多优势实现反而简单了
整体实现内容分析 首先在头文件先定义结构体和各个功能函数的声明并把有关的头文件包含上去。各个函数如何实现的已在实验步骤描述清楚这里就不在赘述了主要是对各个函数的实现用到malloc动态开辟新节点的空间用assert断言确保指针有效通过画图来帮助理清代码实现的思路指针的指向如何要考虑哪些情况。然后再测试代码中将上述代码都进行测试显示结果。 1.头文件编码实现
1、
2、 #pragma once
3、 #include stdio.h
4、 #include stdlib.h
5、 #include assert.h
6、 #include stdbool.h
7、
8、 typedef int LTDataType;
9、 // 带头双向循环链表结构体
10、 typedef struct ListNode
11、 {
12、 struct ListNode* next;
13、 struct ListNode* prev;
14、 LTDataType data;
15、 }ListNode;
16、 ListNode* ListInit();//链表初始化
17、 void ListDestory(ListNode* phead);//删除链表
18、 void ListPrintFront(ListNode* phead);//链表顺序输出
19、 void ListPrintBack(ListNode* phead);//链表逆序输出
20、 void ListPushBack(ListNode* phead, LTDataType x);//尾插
21、 void ListPushFront(ListNode* phead, LTDataType x);//头插
22、 void ListPopFront(ListNode* phead);//头删
23、 void ListPopBack(ListNode* phead);//尾删
24、 ListNode* ListFind(ListNode* phead, LTDataType x);//查找
25、 void ListInsert(ListNode* pos, LTDataType x);// pos位置之前插入x
26、 void ListErase(ListNode* pos);// 删除pos位置的值
27、 bool ListEmpty(ListNode* phead);判空函数
2.代码功能实现
1这是生成新节点函数实现。
代码实现思路详解 //用malloc动态开辟新节点的空间把数值赋值给新节点 //,newnode的next和prev指针指向空。 ListNode* BuyListNode(LTDataType x)
{ListNode* newnode (ListNode*)malloc(sizeof(ListNode));newnode-data x;newnode-next NULL;newnode-prev NULL;return newnode;
}2)生成带头结点的空链表函数实现。
代码实现思路详解 //2)生成带头结点的空链表将头结点的指针都指向自己即可。 ListNode* ListInit()
{ListNode* phead BuyListNode(0);phead-next phead;phead-prev phead;return phead;
}3)删除链表函数实现。
代码实现思路详解 //3)先用assert断言以下确保phead指针不为空生成cur指针先指向第一个结点位置。用while循环执行删表在定义一个next指针指向cur的下一个结点free掉cur指向的结点cur移动到next位置。最后删除头结点即可 // void ListDestory(ListNode* phead)//删除链表
{assert(phead);ListNode* cur phead-next;while (cur ! phead){ListNode* next cur-next;free(cur);cur next;}free(phead);phead NULL;
}4)顺序输出链表函数实现。
代码实现思路详解 //4)顺序输出链表。先assert断言确保指针有效。定义一个指向链表首结点的指针打印完一个cur到下一个节点知道cur回到phead为止。 void ListPrintFront(ListNode* phead)
{assert(phead);ListNode* cur phead-next;while (cur ! phead){printf(%d , cur-data);cur cur-next;}printf(\n);
}5)尾插函数实现。
代码实现思路详解 //5尾插函数。先assert确保指针有效性定义tail指针指向最后一个节点然后生成新节点然后通过指针将tail指向的节点与新生成的节点相连新生成的节点与哨兵位头结点相连 void ListPushBack(ListNode* phead, LTDataType x)
{assert(phead);ListNode* tail phead-prev;ListNode* newnode BuyListNode(x);tail-next newnode;newnode-prev tail;newnode-next phead;phead-prev newnode;
}6头插函数实现。
代码实现思路详解 //6头插函数实现。先assert断言一下确保传入进来的指针有效。定义一个指向首节点的指针然后生成一个新节点让新节点与头结点相连让新节点的next指针指向原来首节点原来首节点的prev指向新节点让新节点位于原来首节点的前面从而实现头插。 void ListPushFront(ListNode* phead, LTDataType x)
{assert(phead);ListNode* first phead-next;ListNode* newnode BuyListNode(x);phead-next newnode;newnode-prev phead;newnode-next first;first-prev newnode;
}
7头删函数实现。
代码实现思路详解 //7头删函数实现。assert确保传入指针有效和确保头结点不要被删掉。定义first指针指向链表首节点second指向first下一个。然后让头结点与second指针指向的节点相连然后free掉first指向的节点。 void ListPopFront(ListNode* phead)
{assert(phead);assert(phead-next ! phead);ListNode* first phead-next;ListNode* second first-next;phead-next second;second-prev phead;free(first);first NULL;}8尾删函数的实现。
代码实现思路详解 //8尾删函数的实现。头删函数实现。assert确保传入指针有效和确保头结点不要被删掉。定义tail函数指向尾节点定义prev指针指向tail的前一个节点让prev指向的那个节点与头结点相连然后删掉tail指向的尾节点实现尾删。 void ListPopBack(ListNode* phead)
{assert(phead);assert(phead-next ! phead);ListNode* tail phead-prev;ListNode* prev tail-prev;prev-next phead;phead-prev prev;free(tail);tail NULL;}9查找函数实现。
代码实现思路详解 //9查找函数先assert断言确保传入指针有效性定义一个cur指向首节点然后利用while遍历链表找到的话就返回指针。找不到则返回空。 ListNode* ListFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur phead-next;while (cur ! phead){if (cur-data x){return cur;}cur cur-next;}return NULL;
}
10pos位置之前插入x的函数实现。
代码实现思路详解 // 10pos位置之前插入x。定义一个prev指针指向pos指向的前一个节点然后新生成一个节点通过指针相连方式将新生成的节点放到pos与prev的中间。 void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* prev pos-prev;ListNode* newnode BuyListNode(x);// prev newnode posprev-next newnode;newnode-prev prev;newnode-next pos;pos-prev newnode;
}11删除pos位置的值的函数实现。
代码实现思路详解 // 11删除pos位置的值。定义一个prev指针指向pos前一个节点定义一个next指向pos后一个节点然后让这两个节点相连删掉pos指向的节点。 void ListErase(ListNode* pos)
{assert(pos);ListNode* prev pos-prev;ListNode* next pos-next;prev-next next;next-prev prev;free(pos);
}12逆序输出的函数实现。
代码实现思路详解 //12)逆序输出函数实现。定义一个phead指针指向尾节点从后往前遍历链表直到cur走到头结点为止。 void ListPrintBack(ListNode* phead)
{assert(phead);ListNode* cur phead-prev;while (cur ! phead){printf(%d , cur-data);cur cur-prev;}printf(\n);
}13判空函数实现。
代码实现思路详解 //13判空函数实现只要phead的前指针指向自己则认为这链表为空链表。 bool ListEmpty(ListNode* phead)
{assert(phead);if (phead-prev phead){return 1;}return -1;
3.测试文件源码分享 #include SlistNode.hvoid TestList1()
{//创建带头节点的空双向链表ListNode* plist ListInit();//判空int ret ListEmpty(plist);if (ret 1){printf(链表为空\n);}else{printf(链表不为空\n);}//尾插1,2,3,4,5ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);ListPrintFront(plist);//头插0,-1ListPushFront(plist, 0);ListPushFront(plist, -1);ListPrintFront(plist);//头删三个数据ListPopFront(plist);ListPopFront(plist);ListPopFront(plist);ListPrintFront(plist);//尾删一个数据ListPopBack(plist);ListPrintFront(plist);//判空int ret1 ListEmpty(plist);if (ret1 1){printf(链表不为空\n);}else{printf(链表为空\n);}// 查找附带着修改的作用ListNode* pos ListFind(plist, 3);if (pos){pos-data * 10;printf(找到了并且节点的值乘以10\n);}else{printf(没有找到\n);}ListPrintFront(plist);//在pos前插入一个300ListInsert(pos, 300);ListPrintFront(plist);//删除pos位置的节点ListErase(pos);//顺序输出链表数据ListPrintFront(plist);//逆序输出链表数据ListPrintBack(plist);
//删除链表ListDestory(plist);}int main()
{TestList1();return 0;
}
程序功能测试结果图
总结撒花 本篇文章旨在分享详解C语言动态实现带头结点的双向循环链表结构。希望大家通过阅读此文有所收获实现带头结点的双向循环链表结构相比于单链表结构更加复杂一点它的成员相比单链表多了一个指针。本次实现难点在于对指针的运用和对多种情况的考虑。在实现前一定要通过画图的方式将思路和需要注意的情况想清楚然后再来尝试用代码进行实现。基本实现出双链表后可以思考能不能优化代码的问题。 如果我写的有什么不好之处请在文章下方给出你宝贵的意见。如果觉得我写的好的话请点个赞赞和关注哦~