当前位置: 首页 > news >正文

单向循环链表超详细精讲 | 带头节点带头指针 + 完整可运行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.更新尾指针(只有在第一次插入时候)
  1. 创建新节点 ------>link_loop *new_node = malloc(sizeof(link_loop));

  1. 更新新节点 ------>new_node->next = link_loop->header.next;

  1. 更新头节点 ------>link_loop->header.next = new_node;

  1. 更新尾指针(只有在第一次插入时候) ------>link_loop->rear = new_node;

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;if(link_loop->rear==&link_loop->header){link_loop->rear=new_node;}
1.2 尾插
1.创建新节点 2.更新新节点 3.更新尾指针的next 3.更新尾指针
  1. 创建新节点 ------>LoopNode *new_node = malloc(sizeof(LoopNode));

  2. 更新新节点 ------>new_node->next = link_loop->rear->next;

  1. 更新尾指针的next ------>link_loop->rear->next = new_node;

  2. 更新尾指针 ------>link_loop->rear = new_node;

1.创建新节点 2.更新新节点 3.更新尾指针的next 3.更新尾指针
LoopNode*new_node=malloc(sizeof(LoopNode));//其实这里也展现了我们在 单链表 中所说的 备份思想new_node->next=link_loop->rear->next;link_loop->rear->next=new_node;link_loop->rear=new_node;
2.删除相关
其实这里的删除和单链表那里的删除完全一样!!! 1.引入辅助指针p,p找到待删除位置的前一个节点 2.引入辅助指针备份待删除位置 tmp 3.修改前驱节点的 next 指针,跳过待删除节点,重新衔接链表 4.删除tmp
  1. 引入辅助指针p,p找到待删除位置的前一个节点 ------>LoopNode *p = 前驱节点

  2. 引入辅助指针备份待删除位置 tmp ------>LoopNode *tmp = p->next;

  3. 修改前驱节点的 next 指针,跳过待删除节点,重新衔接链表 ------>p->next = tmp->next;

  4. 删除tmp ------>free(tmp);

1.引入辅助指针p,p找到待删除位置的前一个节点 2.引入辅助指针备份待删除位置 tmp 3.修改前驱节点的 next 指针,跳过待删除节点,重新衔接链表 4.删除tmp
LoopNode*p=前驱节点 LoopNode*tmp=p->next;p->next=tmp->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.next=link_loop->rear=&link_loop->header;//表中的节点数量为0link_loop->num=0;}
2.头插
intinsertLinkLoopHeader(LinkLoopList*link_loop,Element value){//1 先有新节点LoopNode*node=malloc(sizeof(LoopNode));if(node==NULL){return-1;}//插入代码node->val=value;node->next=link_loop->header.next;link_loop->header.next=node;//判断尾指针是否需要更新if(link_loop->rear==&link_loop->header){link_loop->rear=node;}//增加链表中节点的数量++link_loop->num;return0;}
3.尾插
intinsertLinkLoopRear(LinkLoopList*link_loop,Element value){//1 先有新节点LoopNode*node=malloc(sizeof(LoopNode));if(node==NULL){return-1;}//插入代码node->val=value;node->next=link_loop->rear->next;link_loop->rear->next=node;link_loop->rear=node;//增加链表中节点的数量++link_loop->num;return0;}
4.遍历显示
voidshowLinkLoopList(constLinkLoopList*link_loop)//这里加const 因为是只读{//引入辅助指针nodeLoopNode*node=link_loop->header.next;//单向循环链表 首尾相连while(node!=&link_loop->header){printf("%d ",node->val);//不断向后遍历node=node->next;}printf("\n");}
5.删除节点
intdeleteLinkLoopList(LinkLoopList*link_loop,Element value){//引入辅助指针nodeLoopNode*node=&link_loop->header;//找到待删除位置的前一个节点while(node->next!=&link_loop->header&&node->next->val!=value){node=node->next;}//删除代码if(node->next->val==value){LoopNode*temp=node->next;node->next=temp->next;free(temp);//减少链表中节点的数量--link_loop->num;}//没找到要删除的节点else{printf("NO %d element!\n",value);}return0;}
6.释放整个数据域 不释放头(头置空)
voiddestroyLinkLoopList(LinkLoopList*link_loop){//引入辅助节点nodeLoopNode*node=link_loop->header.next;while(node!=&link_loop->header){//删除代码LoopNode*tmp=node;node=node->next;free(tmp);--link_loop->num;}//最后删除完毕 打印链表中的节点数量printf("Table %d element!\n",link_loop->num);//头置空link_loop->rear=NULL;link_loop->header.next=NULL;}
测试案例
main函数
voidtest03(){LinkLoopList table;//初始化表initLinkLoopList(&table);//循环尾插for(inti=0;i<10;i++){insertLinkLoopRear(&table,i+100);}//头插insertLinkLoopHeader(&table,520);//遍历展示showLinkLoopList(&table);printf("=======================\n");//删除节点deleteLinkLoopList(&table,100);//遍历展示showLinkLoopList(&table);//销毁该表的元素区域 头置空destroyLinkLoopList(&table);}intmain(){test03();return0;}
输出结果
520100101102103104105106107108109=======================520101102103104105106107108109Table0element!

2.带头指针的单向循环链表

​ 经过上面的带头节点的单向循环链表的理解 这个可以说非常简单了
​ 我们可以延用在单链表中所讲的(具体参考主页数据结构专栏)最万金油的思路

引入辅助节点,充当头节点

​ 嘻嘻嘻嘻 单向循环链表部分到此结束😆😆

​ (有错误欢迎指出) (疑问也是)❤️❤️😍😍💖💖

http://www.jsqmd.com/news/928238/

相关文章:

  • 车载AI Agent Harness:行车安全与交互管控
  • 生成式AI赋能无障碍开发:从设计到测试的实践指南
  • 波普尔主义百年灾难清单:系统性尸检报告
  • GPT-Image-2迭代亮点解析
  • 保姆级教程:在Ubuntu 20.04上从源码编译运行ORB-SLAM3(含ROS1/ROS2配置)
  • 设计模式深度解析:从六大原则到Spring源码,面试通关全攻略
  • 山东大学创新实训(六)--基于Multi-Agent的剧本杀平台博客
  • 第三周进度
  • 2026年最新厦门市金银首饰回收+金条金币+铂金K金 高价回收;实体老店回收黄金 多年口碑 交易放心;TOP5实力权威排行榜推荐+联系方式 - 亦辰小黄鸭
  • 2026年最新汕头市金银首饰回收+金条金币+铂金K金 高价回收;实体老店回收黄金 多年口碑 交易放心;TOP5实力权威排行榜推荐+联系方式 - 亦辰小黄鸭
  • 第五章:年终
  • Product Hunt 每日热榜 | 2026-05-31
  • 10. JavaArrayList 核心笔记
  • 扔掉塑料尺:给未来孤勇者的科学排毒指南
  • [分享]EssentialPIM安卓版(手机个人信息管理软件)
  • 告别静音!Windows 11系统声音保姆级配置指南(附完整音效清单与事件对照表)
  • 智慧火灾巡检-基于深度学习火灾烟雾识别系统,森林火灾识别系统。森林火灾检测 无人机森林火灾检测
  • 【周报】液冷板块集体跌停,但我在算一笔账
  • 【AI问答】GO代码循环返值
  • GHelper完整指南:华硕笔记本轻量控制神器的终极教程
  • 技术如何重塑人类感知与希望:算法、AR/VR与数据可视化的中介作用
  • 保姆级教程:用Python和PyTorch从零搭建一个行人重识别(ReID)原型系统
  • 基于YOLOv8的美国手语手势检测系统 美国手语手势检测数据集训练及应用
  • VSCode配置QT环境
  • 华为eNSP静态路由实验教学
  • 第六章:觉醒
  • 航拍地面目标数据集1713张VOC+YOLO格式
  • Ubuntu 远程登录配置
  • 礼盒定制避坑指南!新手品牌常见问题总结
  • 工厂设备预测性维护的必要性与实践案例