双向链表的实现

这篇具有很好参考价值的文章主要介绍了双向链表的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  在本次的博客当中我们来向大家介绍一下双向循环链表,在介绍双向循环链表之前我们需要先来了解一下所有的链表的种类。

  我们的链表大致分为八种:单向链表,双向链表,带头结点的链表,不带头结点的链表,循环链表,不循环的链表。经过组合一共分为八种。(单向不带头节点不循环的链表,双向带头结点循环的链表......)

  我们之前实现过一个单项链表。单项链表是我们在题目中最常见的题目类型,但是他不是最实用的,因为我们想要在特定的节点前方插入一个数据的时候就需要从头开始遍历,找到我们目标节点的前一个位置,之后才可以进行插入等操作。但是对于双向链表来说,我们就不需要从头开始进行遍历了,我们结构体当中会自动存储一个指向前一个节点的指针,便于我们进行操作。

  双向带头循环链表逻辑结构如下:

双向链表的实现   我们主要需要实现的链表当中的函数如下:

双向链表的实现

  在准备函数的书写的之前我们要像我们编写单项链表的一样,构建一个结构体,作为我们每一个节点的模板,便于后面使用。所示代码如下:

双向链表的实现 

      🌵ListCreate函数

  在我们第一次构建循环链表的时候,最重要的就是创建头节点,我们需要梳理好我们的逻辑,当我们的链表当中只存在我们的头节点的时候,(也就代表我们我们链表当中的数据项为0)我们同样需要构建一个循环链表,只不过我们的循环当中只存在一个头节点。就像是下面的结构所示:
双向链表的实现 

  我们要完成的是我们对于头节点的初始化的函数。所示代码如下:

双向链表的实现

  首先我们向堆区请求分配一个结构体大小的空间,之后将我们的头节点的指针更改为我们开辟出来的空间的地址,之后将我们节点当中的数据初始化为 -1 并将我们的前一个指针和后一个指针均指向我们该节点。需要注意的是,我们有两种改变头节点的方式,第一种是在我们的参数当中传入一个二级指针,直接更改我们头节点的地址的值。第二种是让我们的函数返回处理好的地址,并在主函数当中使用phead进行接收。

      🌵ListPushBack函数

  在完成初始化节点之后我们就可以开始向我们的链表当中尝试着存储数据了,我们先来构建一个尾插函数,代码如下:
双向链表的实现  首先我们开辟一个新的节点进行接收我们创建的新的节点。

双向链表的实现   之后我们想要将我们的新节点连接进入我们的链表当中,我们会发现想要在链表的尾部插入其实和在我们的phead之前插入是一样的道理,因为我们每一次遍历链表都是从phead开始的,所以最后遍历到的节点只需要在我们头节点的前方即可。我们将节点链接进入我们的链表当中:

双向链表的实现  就像是我们上图中所示的那样,我们需要更改四个指针的链接即可。但是我们需要注意的是我们需要提前创建一个结构体指针将我们原链表当中的尾节点保存起来,不然当我们更改了phead头指针之后就会丢失我们尾节点的地址。 

      🌵ListPrint函数

  在完成了数据的插入之后我们仅仅在理论上完成了循环链表的构建但是我们要想查看就还需要构建一个打印函数。

双向链表的实现

  对于打印函数我们依旧是遍历整个链表,需要我们注意的也就是循环的结束条件了,循环链表在我们查找到最后一个节点的时候下一个节点就会回到我们的头节点,所以我们只需要判断我们节点的下一项是否为头节点即可。结合我们尾插函数进行代码的检测:

双向链表的实现

      🌵ListPushFront函数

  当我们完成尾插函数之后和我们尾插函数逻辑相类似的就是我们的头插函数,甚至我们还可以将我们的尾插函数直接复制粘贴到我们的头插函数当中,只需要修改部分逻辑即可:

双向链表的实现  唯一不同的就是我们对于链表的头插函数需要将我们新开辟的节点插入到我们我们头节点的后面

双向链表的实现

  在这里我们需要创建一个结构体指针变量保存我们原来链表当中phead节点的下一个节点的地址,原理和我们的尾插函数相同。运行效果如下:
双向链表的实现

      🌵ListPopFront函数

  在构建完我们的节点增加的函数之后就可以构建我们的节点删除的函数了:

双向链表的实现

  首先我们需要判断我们链表当中是否存在存储数据的节点,只有存储数据的节点的时候我们才需要进行删除否则就直接返回即可。否则再删除的话就有可能破坏循环链表的结构。我们使用一个结构体指针存储我们第二个数据节点之后就可以删除第一个节点了,之后再进行略微的代码的修改即可。双向链表的实现   我们在这里需要更改两个指针链接即可,就像是上图中所示的那样,我们不需要管拆下来的节点的指针指向,因为我们将其释放之后就会将其置为空,不在对其进行使用。 代码测试如下:

双向链表的实现

      🌵ListPopBack函数

  和我们头删函数类似的是我们的尾删函数,我们同样可以将我们的代码复制粘贴一份进行复用:双向链表的实现

   同样的我们需要先对链表进行判空操作,之后将我们链表当中phead的前一个节点按照同样的逻辑进行删除即可。运行结果如下:

双向链表的实现

      🌵 ListFind函数

  之后再来构建我们的查找函数。

双向链表的实现  我们第一步需要做的同样是对链表进行判空,如果链表当中为空就可以直接返回NULL,并提示无法进行查找。否则就进行链表的遍历,逻辑和我们打印函数类似,直到我们我们查找的节点下一个指向头节点即可结束,如果在遍历途中就可以返回节点的地址,如果没有返回并且循环结束就代表没有找到,就返回空指针。测试效果如下:

双向链表的实现 

      🌵ListInsert函数

  有了查找函数之后我们的在指定位置插入删除的函数构建起来就方便多了。还记得我们在单链表的构建过程当中,在我们指定节点的位置前面插入新节点的时候,需要进行遍历,会造成效率上面的问题。代码如下:

双向链表的实现

  对于链表节点的插入逻辑和我们的头插尾插相似。双向链表的实现   测试效果如下:

双向链表的实现

      🌵ListErase函数

  之后删除我们指定位置的节点,代码编写逻辑和我们的头删类似:

双向链表的实现

  因为我们向函数的形参部分传入的是一个指针,我们在查找时候接收到的指针代表着这个元素已经存在,那么我们只需要直接使用即可,无需考虑链表当中是否为空的情况。运行效果如下:

双向链表的实现

      🌵ListDestory函数

  最后我们在使用完我们的链表之后需要将我们的每一个节点都返回给我们的操作系统,否则就会存在内存泄露的危险,因此我们最后还需要创建一个销毁函数。代码如下:

双向链表的实现

  我们需要提前创建一个结构体变量接收我们下一步骤当中想要释放的节点,循环释放节点的逻辑和我们遍历结构体相似,我们依旧将我们的循环结束条件定义为判断下一个地址是否为phead。

  在编写完上述代码之后我们的循环链表也就正式编写结束了,感谢您的观看,下次博客再见。 文章来源地址https://www.toymoban.com/news/detail-428560.html

到了这里,关于双向链表的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 数据结构——双向链表的实现

    注意: 双向链表又称带头双向循环链表 这⾥的“带头”跟前⾯我们说的“头节点”是两个概念,实际前⾯的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表⾥的头节点,实际为“ 哨兵位 ”,哨兵位节点不存储任何有效元素,只

    2024年02月06日
    浏览(46)
  • 数据结构:双向链表的实现(C实现)

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 本篇博客,将要实现的是 带头双向循环链表 ,该结构实现尾插,尾删只需要O(1)的时间复杂度。 其结构如下所示: 既然要实现的链表是双向循环的,那么对于指针域,我们就需要 指向节点上一个的指针 和 指向节点

    2024年02月14日
    浏览(49)
  • 北邮22信通:复习补充:双向链表的实现

    北邮22信通一枚~    跟随课程进度每周更新数据结构与算法的代码和文章  持续关注作者  解锁更多邮苑信通专属代码~ 获取更多文章  请访问专栏: 北邮22信通_青山如墨雨如画的博客-CSDN博客 **说明** 最近复习看到书后有双向链表的题目,编出来供大家复习~ ********* 目录

    2024年02月07日
    浏览(53)
  • 基于双向链表的通讯录C语言实现

    关于双向链表的详细了解请见博主的另一篇博客,本文旨在对单链表进行应用,采用C语言编写。

    2024年04月17日
    浏览(121)
  • 【数据结构】—带头双向循环链表的实现(完美链表)

    链表结构一共有八种形式,在前面的文章里已经讲完了不带头单向非循环链表的实现,但是我们发现该链表实现尾插与尾删时比较麻烦,要先从头节点进行遍历,找到尾节点,时间复杂度为O(N),而本次所讲的带头双向循环单链表,则可以直接找到尾节点。 虽然该链表看起来

    2024年01月25日
    浏览(60)
  • 算法竞赛基础:C++双向链表的结构和实现(普通链表、List、静态链表)

    本文将会介绍在算法竞赛中双向链表的几种使用方式,适合有一定基础的人阅读。 一般来说,普通的链表结构是这样的: next指针指向下一个链表,这样的结构只能够支持单向查询。 双向链表,顾名思义,就是可以支持双向的访问和查询。 也就是这样的: 这种链表为访问前

    2024年01月24日
    浏览(40)
  • 【数据结构】双向链表的增删查改(C 代码实现)

    引入双向链表:关于单链表的问题与讨论 单链表存在的毛病: 因为单链表 只能单向 遍历链表, 对于 前插 这个操作,单链表必 须得找到所需前插节点位置的前一个 ,那么这时就得 从头指针重新遍历一次 链表,会造成时间复杂度大大增加。 没有头节点(哨兵位)无法删除

    2024年02月08日
    浏览(51)
  • 数据结构:链表基础OJ练习+带头双向循环链表的实现

    目录 一.leetcode剑指 Offer II 027. 回文链表 1.问题描述 2.问题分析与求解 (1) 快慢指针法定位链表的中间节点 (2) 将链表后半部分进行反转 附:递归法反转链表 (3) 双指针法判断链表是否回文 二.带头双向循环链表的实现 1.头文件 2.节点内存申请接口和链表初始化接口 3.链表的打

    2024年02月02日
    浏览(49)
  • 数据结构_链表_双向循环链表的初始化、插入、删除、修改、查询打印(基于C语言实现)

    版本: 2024年4月26日 V1.0 发布于博客园 目录 目录 双向循环链表公式 初始化双向循环链表 构建双向循环链表结点 创建一个空链表(仅头结点) 创建一个新结点 插入数据 头插 中插 尾插 删除数据 头删 中删 尾删 查询打印数据 遍历打印 测试 测试结果: 完整代码 DoubleCirLList.h

    2024年04月27日
    浏览(51)
  • 双向链表的构建

    上篇内容给大家带来了单链表的构建,那么本期内容继续给大家带来链表的相关内容---- 双向链表 。 什么是双向链表?双向链表与单链表有什么区别? 在单链表中,咱们每个结点的指针域存放了后继指针,以便于链接每个结点,随后讲到按位查找,从头结点开始,设置工作

    2024年01月16日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包