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

单向循环链表超详细精讲 | 带头节点带头指针 + 完整可运行c语言代码 - Fa-Mian

单向循环链表

1.带头节点的单向循环链表

前置知识

所谓单向循环链表就是在普通单向链表基础上,把最后一个节点的 next 指针不再置为 NULL,而是指向链表第一个节点(头节点/首元节点)

​ 先展示下链表的样子(这里我加了了个count 给写成了结构体) (count用来统计链表中的节点数量)

image-20260531144554599

1.插入相关

1.1头插
1.创建新节点
2.更新新节点
3.更新头节点
4.更新尾指针(只有在第一次插入时候)
  1. 创建新节点 ------> link_loop *new_node = malloc(sizeof(link_loop));

image-20260531155834410

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

image-20260531160033562

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

image-20260531160130199

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

image-20260531174716655

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));

    image-20260531162725377

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

    image-20260531163419023

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

    image-20260531163522876

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

    image-20260531163626366

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;

    image-20260531164721595

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

    image-20260531164937775

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

    image-20260531165015339

1.引入辅助指针p,p找到待删除位置的前一个节点
2.引入辅助指针备份待删除位置 tmp
3.修改前驱节点的  next  指针,跳过待删除节点,重新衔接链表
4.删除tmp
LoopNode *p = 前驱节点
LoopNode* tmp = p->next;
p->next = tmp->next;
free(tmp);

头文件部分

typedef int Element;typedef struct _loop_node {Element val;struct _loop_node* next;
}LoopNode;//定义单向循环链表的头结构
typedef struct {LoopNode header;LoopNode* rear;      int num;
}LinkLoopList;//1.初始化接口
void initLinkLoopList(LinkLoopList* link_loop);//2.头插
int insertLinkLoopHeader(LinkLoopList* link_loop, Element value);
//3.尾插
int insertLinkLoopRear(LinkLoopList* link_loop, Element value);//4.遍历显示
void showLinkLoopList(const LinkLoopList* link_loop);//5.删除节点
int deleteLinkLoopList(LinkLoopList* link_loop, Element value);//6.释放整个数据域 不释放头(头置空)
void destroyLinkLoopList(LinkLoopList* link_loop);

实现

1.初始化接口

void initLinkLoopList(LinkLoopList* link_loop)
{//刚开始就是自己指自己link_loop->header.next = link_loop->rear = &link_loop->header;//表中的节点数量为0link_loop->num = 0;
}

2.头插

int insertLinkLoopHeader(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;return 0;
}

3.尾插

int insertLinkLoopRear(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;return 0;
}

4.遍历显示

void showLinkLoopList(const LinkLoopList* link_loop) //这里加const 因为是只读
{//引入辅助指针nodeLoopNode* node = link_loop->header.next;//单向循环链表 首尾相连while (node != &link_loop->header) {printf("%d ", node->val);//不断向后遍历node = node->next;}printf("\n");
}

5.删除节点

int deleteLinkLoopList(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);}return 0;
}

6.释放整个数据域 不释放头(头置空)

void destroyLinkLoopList(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函数

void test03()
{    LinkLoopList table;//初始化表initLinkLoopList(&table);//循环尾插for (int i = 0;i < 10;i++) {insertLinkLoopRear(&table, i + 100);}//头插insertLinkLoopHeader(&table, 520);//遍历展示showLinkLoopList(&table);printf("=======================\n");//删除节点deleteLinkLoopList(&table, 100);//遍历展示showLinkLoopList(&table);//销毁该表的元素区域 头置空destroyLinkLoopList(&table);
}int main()
{test03();return 0;
}

输出结果

520 100 101 102 103 104 105 106 107 108 109
=======================
520 101 102 103 104 105 106 107 108 109
Table 0 element!

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

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

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

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

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

http://www.zskr.cn/news/1436785.html

相关文章:

  • 手机号码定位终极方案:5分钟构建免费高效的归属地查询系统
  • 青岛黄金回收怎么选?5.31金价 + 靠谱门店全攻略 - 速递信息
  • 3步完成《艾尔登法环》角色迁移:告别存档损坏的终极方案
  • 合肥高科经济技工学校招生办公室电话号码是多少?——官网最新发布! - 教育为先
  • 新疆伊犁六日游旅行社盘点 聚焦纯玩品质线路 - 互联网科技品牌测评
  • 20252919 2025-2026-2 《网络攻防实践》第十次作业
  • 软件设计师学习记录
  • RAG落地不踩坑!Embedding模型选型最全攻略,新手直接抄作业
  • 现在不重构增长链路,Q3将错失最后窗口期:Gemini 2024下半年用户增长生死线(含合规红线清单)
  • 小县城赢家为何奔向大城市?
  • Cache的三种映射方式(直接/全相联/组相联)
  • 用NEAT-Python教AI玩XOR游戏:从零开始手把手配置你的第一个神经进化项目
  • 自动化产线响应快且抗干扰,广东犸力获评气压传感器十大品牌 - 品牌速递
  • Gemini推送延迟高达3秒?揭秘Google官方未公开的4层缓冲机制及3步调优法
  • 终极指南:3分钟快速解决Windows 11任务栏拖放失灵问题
  • 如何完全掌控微信聊天数据:WeChatMsg终极本地化导出指南
  • 构建可控的 AI Agent Harness Engineering:约束、规则与政策引擎
  • 新能源汽车电机测试必备,广东犸力扭矩传感器权威测评报告 - 品牌速递
  • 81k Star! RAGFlow:开源RAG引擎,深度文档理解+Agent编排
  • Video2X终极指南:5个简单步骤实现AI视频增强与画质修复
  • 绝对值 - ace-
  • 告别‘调包侠’:在EduCoder上用纯NumPy实现CNN前向传播的避坑指南
  • OpenCode 源码解读报告
  • 5分钟精通跨平台资源下载:res-downloader全面实战指南
  • 面向法律合规Agent的Harness规则引擎
  • RAG :构建测试数据集
  • 能快速导出无水印的AI证件照一键生成工具有哪些?2026免费无水印AI证件照工具推荐 - 科技大爆炸
  • 197、运动控制中的行业应用:四足机器人步态控制
  • WarcraftHelper:让经典魔兽争霸3在现代电脑上完美运行的8大优化方案
  • 别再只懂理论了!用C语言实战FIR滤波器设计:避坑指南与代码优化技巧