双向链表(双向带头循环)的增删查改的实现(简单易懂)

一:双向链表的概念

每个节点除开存有数据,还有一个指针指向前一个节点,一个指针指向后一个节点,尾节点和哨兵位互相指向,从而形成一个循环。

二:双向链表的实现
第一点:
本文采用三个文件进行实现
1:List.h(对实现函数以及节点的声明)
2:List.c(增删查改的函数的实现)
3:text.c(对程序的使用检测) 

第二点:

本文需要用到的参数和变量

1:plist:实参,头指针
2:phead:形参,头指针

第三点:

所有的函数实现内部第一步永远考虑是否需要对接收到的结构体指针进行断言,这样会更严谨!

1:参数为phead的,一定需要断言,因为不管该链表是否存在节点,都不会为空,因为最少也存在哨兵位的节点。

2:在删除的时候,我们还需要另外assert(phead->next != phead),避免出现只有哨兵位的情况,这样的话,不存在节点让我们去删除。

三:函数的实现讲解

前提:节点的声明

解释:

1:data用来保存节点的值,next用来指向下一个节点,prev用来指向上一个节点。

2:将类型进行一个typedef,方便之后的类型改变带来的修改,只需要修改int即可。

3:将结构体重命名为LTNode,方便之后使用。

第一个函数:创建新节点函数

解释:

1:参数为一个值,将会赋给创建的新节点的data。然后将创建的节点的next置空(会方便后续的操作)。

2:初始化(malloc)顺序表的空间为一个节点的大小,malloc函数的返回值为void*,所以需要强转为LTNode* 的类型,然后该空间才能给新节点使用。

3:malloc开辟失败的检测,以及exit(-1)代表即刻退出。

第二个函数:初始化链表

解释:

初始化一般只会使用一次,用于哨兵位的创建。 

第三个函数:打印链表

解释:

1:断言phead,链表不可能为空,最少都存在哨兵位。

2:打印不需要打印哨兵位,哨兵位本身的data没有意义,所以我们从head(哨兵位的下一个)开始遍历打印。

3:<=>符号是为了更加形象的展示循环,以及phead,是打印出来形象表示哨兵位的。

第四个函数:尾插

解释:

1: 断言phead

2:通过哨兵位的prev找到尾节点,并且放在tail里面,这样方便之后的指针指向的更改。

3:尾插一个节点进来,不但要进行尾节点和尾插节点的循环,还要进行尾插节点和哨兵位的循环。

4:当只有哨兵位的时候,tail也就是哨兵位,以上的步骤依旧可以正常的尾插,所以不需要额外增加情况的判断。

第五个函数:尾删

解释:

1:断言 phead->next是因为避免出现只有哨兵位的情况,这样的话,不存在节点让我们去删除。

2:tail和tailprev节点的创建,方便我们后面进行更改指针的指向。

3:记得释放掉tail。

第六个函数:头插

 解释:

1:断言 

2:头插不仅要进行首节点和头插节点的循环,还要记得进行头插节点和哨兵的循环

3:当只有哨兵位的时候,first也就是哨兵位,以上的步骤依旧可以正常的头插,所以不需要额外增加情况的判断。

第七个函数: 头删

解释:

1: 断言 phead->next是因为避免出现只有哨兵位的情况,这样的话,不存在节点让我们去删除。

2:头删要进行第二个节点和哨兵位循环。

3:释放掉头结点

第八个函数:查找值为x的节点

解释:

1:断言。

2:应该从哨兵的下一个节点开始遍历查找。 

3:循环遍历从哨兵的下一个节点到哨兵的前一个节点,刚好全部遍历,哨兵位不遍历,本身就不属于节点,其次万一x值吻合,也是非法的。

第九个函数:在pos节点前插入一个值为x的节点

解释:

1:断言

2:不仅要进行新节点和pos节点的循环,还要进行新节点和pos前一个节点的循环 

第十个函数:删除pos节点

解释:

1:将pos的前后节点进行循环连接,再释放pos即可 

第十一个函数:计算节点个数

解释:

1:从哨兵位的下一个开始计数到哨兵位的前一个。

第十一个函数:销毁链表

解释:

1:由于所有函数都是采用的一级指针传参,所以这个函数需要调用者在main函数进行一个手动的置空,才能使真正的plist完全的free掉

2:从哨兵位的下一个开始销毁,最后销毁哨兵位 

最后是text.c函数进行一系列测试的运行结果:

头文件的展示:

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值