单向循环链表超详细精讲 | 带头节点带头指针 + 完整可运行c语言代码 文章目录单向循环链表1.带头节点的单向循环链表前置知识1.插入相关1.1头插1.2 尾插2.删除相关头文件部分实现1.初始化接口2.头插3.尾插4.遍历显示5.删除节点6.释放整个数据域 不释放头(头置空)测试案例main函数输出结果2.带头指针的单向循环链表单向循环链表1.带头节点的单向循环链表前置知识所谓单向循环链表就是在普通单向链表基础上把最后一个节点的 next 指针不再置为 NULL而是指向链表第一个节点头节点/首元节点​ 先展示下链表的样子(这里我加了了个count 给写成了结构体) (count用来统计链表中的节点数量)1.插入相关1.1头插1.创建新节点 2.更新新节点 3.更新头节点 4.更新尾指针(只有在第一次插入时候)创建新节点 ------link_loop *new_node malloc(sizeof(link_loop));更新新节点 ------new_node-next link_loop-header.next;更新头节点 ------link_loop-header.next new_node;更新尾指针(只有在第一次插入时候) ------link_loop-rear new_node;1.创建新节点 2.更新新节点 3.更新头节点 4.更新尾指针(只有在第一次插入时候)link_loop*new_nodemalloc(sizeof(link_loop));//其实这里也展现了我们在 单链表 中所说的 备份思想new_node-nextlink_loop-header.next;link_loop-header.nextnew_node;if(link_loop-rearlink_loop-header){link_loop-rearnew_node;}1.2 尾插1.创建新节点 2.更新新节点 3.更新尾指针的next 3.更新尾指针创建新节点 ------LoopNode *new_node malloc(sizeof(LoopNode));更新新节点 ------new_node-next link_loop-rear-next;​更新尾指针的next ------link_loop-rear-next new_node;更新尾指针 ------link_loop-rear new_node;1.创建新节点 2.更新新节点 3.更新尾指针的next 3.更新尾指针LoopNode*new_nodemalloc(sizeof(LoopNode));//其实这里也展现了我们在 单链表 中所说的 备份思想new_node-nextlink_loop-rear-next;link_loop-rear-nextnew_node;link_loop-rearnew_node;2.删除相关其实这里的删除和单链表那里的删除完全一样!!! 1.引入辅助指针pp找到待删除位置的前一个节点 2.引入辅助指针备份待删除位置 tmp 3.修改前驱节点的 next 指针跳过待删除节点重新衔接链表 4.删除tmp引入辅助指针pp找到待删除位置的前一个节点 ------LoopNode *p 前驱节点引入辅助指针备份待删除位置 tmp ------LoopNode *tmp p-next;修改前驱节点的 next 指针跳过待删除节点重新衔接链表 ------p-next tmp-next;删除tmp ------free(tmp);1.引入辅助指针pp找到待删除位置的前一个节点 2.引入辅助指针备份待删除位置 tmp 3.修改前驱节点的 next 指针跳过待删除节点重新衔接链表 4.删除tmpLoopNode*p前驱节点 LoopNode*tmpp-next;p-nexttmp-next;free(tmp);头文件部分typedefintElement;typedefstruct_loop_node{Element val;struct_loop_node*next;}LoopNode;//定义单向循环链表的头结构typedefstruct{LoopNode header;LoopNode*rear;intnum;}LinkLoopList;//1.初始化接口voidinitLinkLoopList(LinkLoopList*link_loop);//2.头插intinsertLinkLoopHeader(LinkLoopList*link_loop,Element value);//3.尾插intinsertLinkLoopRear(LinkLoopList*link_loop,Element value);//4.遍历显示voidshowLinkLoopList(constLinkLoopList*link_loop);//5.删除节点intdeleteLinkLoopList(LinkLoopList*link_loop,Element value);//6.释放整个数据域 不释放头(头置空)voiddestroyLinkLoopList(LinkLoopList*link_loop);实现1.初始化接口voidinitLinkLoopList(LinkLoopList*link_loop){//刚开始就是自己指自己link_loop-header.nextlink_loop-rearlink_loop-header;//表中的节点数量为0link_loop-num0;}2.头插intinsertLinkLoopHeader(LinkLoopList*link_loop,Element value){//1 先有新节点LoopNode*nodemalloc(sizeof(LoopNode));if(nodeNULL){return-1;}//插入代码node-valvalue;node-nextlink_loop-header.next;link_loop-header.nextnode;//判断尾指针是否需要更新if(link_loop-rearlink_loop-header){link_loop-rearnode;}//增加链表中节点的数量link_loop-num;return0;}3.尾插intinsertLinkLoopRear(LinkLoopList*link_loop,Element value){//1 先有新节点LoopNode*nodemalloc(sizeof(LoopNode));if(nodeNULL){return-1;}//插入代码node-valvalue;node-nextlink_loop-rear-next;link_loop-rear-nextnode;link_loop-rearnode;//增加链表中节点的数量link_loop-num;return0;}4.遍历显示voidshowLinkLoopList(constLinkLoopList*link_loop)//这里加const 因为是只读{//引入辅助指针nodeLoopNode*nodelink_loop-header.next;//单向循环链表 首尾相连while(node!link_loop-header){printf(%d ,node-val);//不断向后遍历nodenode-next;}printf(\n);}5.删除节点intdeleteLinkLoopList(LinkLoopList*link_loop,Element value){//引入辅助指针nodeLoopNode*nodelink_loop-header;//找到待删除位置的前一个节点while(node-next!link_loop-headernode-next-val!value){nodenode-next;}//删除代码if(node-next-valvalue){LoopNode*tempnode-next;node-nexttemp-next;free(temp);//减少链表中节点的数量--link_loop-num;}//没找到要删除的节点else{printf(NO %d element!\n,value);}return0;}6.释放整个数据域 不释放头(头置空)voiddestroyLinkLoopList(LinkLoopList*link_loop){//引入辅助节点nodeLoopNode*nodelink_loop-header.next;while(node!link_loop-header){//删除代码LoopNode*tmpnode;nodenode-next;free(tmp);--link_loop-num;}//最后删除完毕 打印链表中的节点数量printf(Table %d element!\n,link_loop-num);//头置空link_loop-rearNULL;link_loop-header.nextNULL;}测试案例main函数voidtest03(){LinkLoopList table;//初始化表initLinkLoopList(table);//循环尾插for(inti0;i10;i){insertLinkLoopRear(table,i100);}//头插insertLinkLoopHeader(table,520);//遍历展示showLinkLoopList(table);printf(\n);//删除节点deleteLinkLoopList(table,100);//遍历展示showLinkLoopList(table);//销毁该表的元素区域 头置空destroyLinkLoopList(table);}intmain(){test03();return0;}输出结果520100101102103104105106107108109520101102103104105106107108109Table0element!2.带头指针的单向循环链表​ 经过上面的带头节点的单向循环链表的理解 这个可以说非常简单了​ 我们可以延用在单链表中所讲的(具体参考主页数据结构专栏)最万金油的思路​引入辅助节点充当头节点​ 嘻嘻嘻嘻 单向循环链表部分到此结束​ (有错误欢迎指出) (疑问也是)❤️❤️