当前位置:首页 » 《我的小黑屋》 » 正文

C语言—双链表

16 人参与  2024年10月15日 15:21  分类 : 《我的小黑屋》  评论

点击全文阅读


一、双向链表的结构

注意:这⾥的“带头”跟前⾯我们说的“头节点”是两个概念,实际前⾯在单链表阶段称呼不严谨,带头链表⾥的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这⾥“放哨的”。
“哨兵位”存在的意义:遍历循环链表避免死循环。

二、双链表实现

注意:这里实现的双链表是指双向带头循环链表

(2.1)基本结构定义

为了双链表的复用性,这里将 int 重命名为LTDataType,后面如果要存储别的数据类型只需要将int更改就可以(自定义类型除外,自定义类型有些函数需要进行一定程度的修改),双链表节点中有一个数据域存储数据,两个指针域,其中 next 存储后继节点,prev 存储前驱节点,这里为了后面使用方便还将结构体类型重命名为LTNode。

(2.2)初始化链表

实现思路:该函数只需要一个参数,即指向头指针的二级指针,之所以用二级指针是因为我们实现的是带头双向循环链表,所以我们需要在该函数中申请一块不存储有效数据的空间,用来作为整个链表的头,并且让链表的头指针指向它,所以我们需要通过形参来实现改变链表头指针指向,所以需要传址调用,而这里的传址传的是头指针的地址,所以用二级指针。初始化时只有一个头节点,所以让它的 next 指针和 prev 指针都指向自己。

具体实现:

(2.3)打印数据

实现思路:因为打印链表数据,所以形参需要链表的头指针,因为头结点是不存储有效数据的,所以循环打印链表数据的时候可以从头节点的下一个节点开始循环,链表是循环的,当遍历回头节点的时候就说明所有有效节点都打印一遍了,而头节点又没有有效数据,所以当遍历到头节点的时候就退出循环。

具体实现:

(2.4)申请新节点

实现思路:先用动态内存申请函数申请出节点大小的空间,然后判断是否申请成功,申请失败报错,申请成功将数据插入,并将 next 指针和 prev 指针都指向自己,最后将申请成功的节点地址返回。(形参是要插入的数据)

具体实现:

(2.5)头部插入删除数据/尾部插入删除数据

(2.5.1)尾部插入

实现思路:该函数需要两个形参,一个用来找到链表的头指针,一个要插入的数据,在函数中调用前面写好的申请节点的函数申请新节点,然后就可以将节点插入链表尾部了,插入节点的写法可以有很多种,如果用下面的方法插入,前两句的顺序无所谓,但是后面两句顺序不可以改变,否则就会出问题。因为按照下图的写法,第三句(52行)中,phead的prev是原链表的尾节点,这句话的意思是让原链表的尾节点的next指针指向新节点,然后再让phead的prev指针指向新节点,这样新节点就成为了新的尾节点,如果交换顺序,先执行第四句,再执行第三句,phead的prev指针就指向新节点了,就不指向原来的尾节点了,那这句话中的next指针就是新节点的next指针而不是原链表尾节点的next指针。

具体实现:

(2.5.2)头部插入

实现思路:该函数需要两个参数,一个用来找到链表的头指针,一个要插入的数据,后面和尾插思路很像,先申请新节点,然后再插在原链表头后面就可以了,还是62,63两行顺序无所谓,64,65两行顺序不能改变。(注意:这是双向带头循环链表,头部插入是指插入在固定的头的后面,而不是插入一个新的头节点)

具体实现:

(2.5.3)尾部删除

实现思路:该函数只需要一个参数,即可以找到链表的头指针即可。因为链表是循环的,所以很容易就可以找到尾节点,就是头节点的前驱节点,我们可以先将要删除的节点用一个临时变量记录下来,先不要着急删除,先将删除节点会影响到的指针域进行重新赋值,然后再删,用临时变量记录要删除的节点避免了因为指针域的改变而找不到要删除的节点。

具体实现:

(2.5.4)头部删除

实现思路:该函数只需要一个形参,即可以找到链表的头指针,头删和尾删的思路很像,先定义一个临时变量记录要删除的节点,然后改变因删除节点受到影响的指针,最后释放节点,需要注意的是这里的头删指的是删除表头的后一个节点。

具体实现:

(2.6)查找

实现思路:该函数需要两个形参,一个用来找到链表的头指针,一个要查找的数据,因为双链表的头节点不存储有效数据,所以我们可以从头节点的下一个节点开始遍历,双链表是循环链表,所以当遍历回头节点的时候说明所有节点都已经遍历一次了,如果还没有找到,就需要退出循环,返回NULL。

具体实现:

(2.7)在pos位置之后插入数据

实现思路:这个函数可以配合查找使用,实现思路和头插,尾插很像,注意一下连接节点时的连接顺序即可。

具体实现:

(2.8)删除pos位置的数据

实现思路:先将pos的前后节点连接上,在释放pos即可。

具体实现:

(2.9)销毁链表

实现思路:我们可以从头节点的后一个节点开始循环删除,在释放当前节点前先将后继节点记录下来,防止释放后找不到,当除头节点外的所有节点都删除后再删除头节点,并将头指针置空。

具体实现:


点击全文阅读


本文链接:http://zhangshiyu.com/post/172190.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1