【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点)

这篇具有很好参考价值的文章主要介绍了【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.带头双向链表的概念

带头双向循环链表(Doubly Circular Linked List with a Head)是一种链表数据结构,它具有以下特点:

头节点(哨兵位):带头双向循环链表包含一个头节点,它位于链表的起始位置,并且不存储实际数据。头节点的前驱指针指向尾节点,头节点的后继指针指向第一个实际数据节点。

循环连接:尾节点的后继指针指向头节点,而头节点的前驱指针指向尾节点,将链表形成一个循环连接的闭环。这样可以使链表在遍历时可以无限循环,方便实现循环操作。

双向连接:每个节点都有一个前驱指针和一个后继指针,使得节点可以向前和向后遍历。前驱指针指向前一个节点,后继指针指向后一个节点。

总结:带头双向循环链表可以支持在链表的任意位置进行插入和删除操作,并且可以实现正向和反向的循环遍历。通过循环连接的特性,链表可以在连续的循环中遍历所有节点,使得链表的操作更加灵活和高效。

二.带头双向循环链表的实现

1.实现框架

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

通过将int定义为LTDataType,可以在代码中使用LTDataType作为数据类型,而不是直接使用int。这样做的好处有以下几点:

  1. 可读性:使用LTDataType作为数据类型可以使代码更具可读性。LTDataType作为一个自定义的数据类型名称,可以更好地表达代码中数据的含义和用途,提高代码的可理解性。
  2. 可维护性:将int定义为LTDataType可以方便地在代码中统一修改数据类型。如果将来需要将数据类型更改为其他类型,只需修改typedef语句中的定义,而不需要在整个代码中逐个修改具体的数据类型,减少了修改的工作量和出错的可能性。
  3. 灵活性:通过使用LTDataType,可以在代码中轻松更改数据类型,而不会对代码的其他部分产生影响。这种抽象化的方式可以使代码更具通用性,便于在不同的场景中重用。

2.动态内存开辟申请

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
此函数是关于一个结点动态申请的实现,包含两个指针域,一个数据域。如果分配成功,它会返回指向该内存块起始位置的指针。你可以使用这个指针来访问和操作所分配的内存。如果分配失败,malloc会返回NULL指针,表示内存分配未成功。

3.链表的初始化

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
链表的初始化就是要创建哨兵位的头节点,此头节点不存储有效数据,并且因一开始不知道指向谁,所以根据双向链表循环的特性,就让该结点的两个指针自己指向自己。

4.链表打印

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
打印链表就是,遍历链表的每一个结点的数据域,开始时用assert断言传过来的结点地址是否为NULL。接着cur用phead->next赋值的原因是,phead传过来的是哨兵位的头节点,它的下一位才是链表真正的头节点(有数据域),接着遍历链表,当cur指针回到哨兵位时,遍历结束。

5. 释放链表所申请的动态内存空间

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
在动态内存使用完后,需要把这部分内存的使用权限还给操作系统,否则会造成内存泄漏。将头节点的下一个节点赋值给cur,让cur遍历链表一遍,当cur遍历完成到phead头节点的时候,释放结束,退出循环。

6.判断链表是否为空。

在上面的释放动态内存函数中用到了另外一个函数LTEmpty,这个函数的作用是用来判断链表是否只有哨兵位,空链表的话是不能进行释放的。为此,引用了布尔值,如果为空则返回true,不空则返回false。

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

7.链表尾部插入节点

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
首先创建一个指针用于存储最后一个节点,防止尾插时找不到,之后将链表与新节点链接起来就可以了。

测试用例:

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
尾插几个数据之后,打印出来,最后将内存返回个操作系统,释放哨兵位,防止内存泄露。
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
这是测试打印出来的数据。

8.链表头部插入节点

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
首先创建一个指针用于存储第一个节点,防止尾插时找不到,之后将链表与新节点链接起来就可以了。

测试用例:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
插入几个数据之后,打印出来,最后将内存返回个操作系统,释放哨兵位,防止内存泄露。

测试数据:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

9.链表尾部删除节点

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
具体怎么实现的都注释在代码边上了,就直接开始测试用例看一下有没有问题。

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
为了方便对比,每次删除一个节点后都有打印一次链表在屏幕上。

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

可以看出这个代码是成功的了,将尾部的三个数据都成功的删除了。
那么再来看一下assert函数能不能起作用,这边故意多删除几个,看会不会报错。
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
这里也是能看见是报错了的,并且能够直接看出来是在list.c文件的第75行出的问题,如果再看一次实现函数的代码的话,确实就能看见是75行的assert报的错误。

10.链表头部删除节点

函数实现:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
测试用例:

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
可以看出,头删也是成功了,因为assert函数的实现是一样的,这边就不过多测试了。

11.查找和修改节点

函数实现:

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
函数的测试用例:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
可以看到这个查找和修改的功能也是成功了。

12.在链表pos之前插入节点

函数实现:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
测试用例:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
数字9也是成功的插入到了3的前面,那么这个函数也是成功的实现了。
而成功的实现了这个函数,我们就可以将这个函数复用到头插和尾插函数当中。
函数复用实现:

  1. 头插:【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
  2. 尾插:【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

13.在链表pos处删除该节点

函数实现:
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
测试用例:

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
可以看到结果也是与我们预期的相符合,这个函数也是成功了。
同样这个函数也是可以复用到头删和尾删中的。

  1. 头删:【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

  2. 尾删:【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

test.c

那么接下来就把所有的代码放在这里。
test.c是函数主题的框架,用来执行函数的功能。
【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

list.c

list.c是每个功能函数具体实现的代码

【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记

list.h

list.h是声明头文件和函数指针以及定义结构体的部分。【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点),数据结构,链表,c语言,笔记
本篇完毕,如有错误,欢迎大佬指正!文章来源地址https://www.toymoban.com/news/detail-860595.html

到了这里,关于【数据结构】带头双向循环链表(小白作品,如果有误,请大佬指点)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】带头双向循环链表

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言阶段(已结束) ❤️ 数据结构与算法(ing) ❤

    2024年01月16日
    浏览(78)
  • 数据结构---带头双向循环链表

    什么是双向带头循环链表? 上面简单的一个非空 带头循环双向链表逻辑图 如何定义一个双向链表? 根据图和代码可以看双向链表就是单链表的每个结点中,在设置一个指向前驱节点的指针 简单认识之后,对他进行初始化(申请一个头节点,让前驱和后驱指针都指向自己) 代码

    2024年02月07日
    浏览(69)
  • 【数据结构】实现带头双向循环链表

    之前我们已经学习了单链表,有了单链表的基础,现在开始学习带头双向循环链表~ 结构最复杂 ,一般用在单独存储数据。 实际中使用的链表数据结构,都是带头双向循环链表 。另外这个结构虽然结构复杂,但是使用代码实现以后会发现 结构会带来很多优势 ,实现反而简单

    2024年02月10日
    浏览(46)
  • 数据结构之带头双向循环链表

    目录 链表的分类 带头双向循环链表的实现 带头双向循环链表的结构 带头双向循环链表的结构示意图 空链表结构示意图 单结点链表结构示意图  多结点链表结构示意图 链表创建结点 双向链表初始化 销毁双向链表 打印双向链表  双向链表尾插 尾插函数测试 双向链表头插

    2024年02月08日
    浏览(73)
  • 数据结构_带头双向循环链表

    相较于之前的顺序表和单向链表,双向链表的逻辑结构稍微复杂一些,但是在实现各种接口的时候是很简单的。因为不用找尾,写起来会舒服一点。(也可能是因为最近一直在写这个的原因) 在实现接口的时候,除了没有找尾,其他的操作和单向链表是差不多的,这里就不多

    2024年04月14日
    浏览(63)
  • 【数据结构】线性表——带头双向循环链表

    带头双向循环链表的优点 1.支持任意位置时间复杂度为O(1)的插入和删除。 2.按照需求申请释放空间,无需担心空间不够用,无需担心浪费。 3.带头可以省去链表为空时的判断,可以使代码更加简约 带头双向循环链表的缺点 1.不可以进行下标随机访问。 2.缓存利用率低 带头双

    2024年02月03日
    浏览(69)
  • 【数据结构】带头双向循环链表及其实现

    目录 1.带头双向循环链表 2.带头双向循环链表实现 2.1初始化 2.2销毁 2.3头插 2.4链表打印 2.5头删数据 2.6尾插数据 2.7尾删数据 2.8链表判空  2.9查找一个数据 2.10在pos位置前插入数据 2.11删除pos位置 2.12求链表的长度 2.顺序表和链表的比较 我们已经实现了无头单向循环链表 带头双

    2024年02月10日
    浏览(45)
  • 数据结构-带头双向循环链表的实现

    前言           带头双向循环链表是一种重要的数据结构,它的结构是很完美的,它弥补了单链表的许多不足,让我们一起来了解一下它是如何实现的吧!         它的节点中存储着数据和两个指针,一个 指针_prev 用来记录前一个节点的地址,另一个指针 _next 用来记录后一

    2024年02月13日
    浏览(49)
  • 数据结构入门指南:带头双向循环链表

    目录 文章目录 前言 1.结构与优势 2.链表实现       2.1 定义链表 2.2 创建头节点 2.3 尾插 2.4 输出链表 2.5 尾删 2.6 头插 2.7头删 2.8 节点个数 2.9 查找 2.10 位置插入 2.11 位置删除 2.12 销毁链表  3. 源码 总结         链表一共有8种结构,但最常用的就是无头单向链表、和带头

    2024年02月14日
    浏览(51)
  • 数据结构: 线性表(带头双向循环链表实现)

    之前一章学习了单链表的相关操作, 但是单链表的限制却很多, 比如不能倒序扫描链表, 解决方法是在数据结构上附加一个域, 使它包含指向前一个单元的指针即可. 那么怎么定义数据结构呢? 首先我们先了解以下链表的分类 链表的结构非常多样, 以下情况组合起来就有 8 中链表

    2024年02月14日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包