![447c60d54c26569cca213548cfcc9c1d.png](https://i-blog.csdnimg.cn/blog_migrate/5adef735044d0728993df17f0621e83d.png)
双向链表和双向循环链表的区别就是在尾节点的指向。双向循环链表的尾节点的next指向NULL。双向循环链表的尾节点的next指向首元结点,首元节点的prior指向尾节点。
关于双向循环链表,可以看上一篇文章
https://zhuanlan.zhihu.com/p/12556623zhuanlan.zhihu.com双向循环链表的节点和双向链表一样
0.0.双向循环链表的节点
和双向链表一样,都包含前驱,元素,后继
![99ecc19866486d627380827da342bd16.png](https://i-blog.csdnimg.cn/blog_migrate/a2a28aff93582f3168fef6a620504fbb.png)
0.1空链表
前驱和后继都是指向自己的
![672eb1d16c52c8818658f30fdc35c2f7.png](https://i-blog.csdnimg.cn/blog_migrate/e408a0c17637aa875f9601041981466f.png)
0.2.非空双向循环链表
![cb6701c5b9012aa437bca85cc73af6ef.png](https://i-blog.csdnimg.cn/blog_migrate/0a4f19e83b1204022e68c9701bc2654a.jpeg)
0.3准备工作
#define ERROR 0
1.初始化双向循环链表
// 初始化链表
2.遍历双向循环链表
// 遍历双向循环链表
3.插入数据
双向循环链表的插入和双向链表类似
![7f17f5bacb1e7ecc72fd89ed78ec7226.png](https://i-blog.csdnimg.cn/blog_migrate/16e73d9e6d53c83404d2fcb614c6c85a.jpeg)
①遍历得到需要插入位置的上一个节点(p)
②创建需要插入的节点temp
③让p的next节点的prior指向temp (p.next.prior -> temp),这时③2就断开了
④让temp的next指向p的next (temp.next -> p.next)
⑤让p的next指向temp (p.next->temp),这时⑤2断开
⑥让temp的prior指向p
注意:上面的③和④必须在⑤和⑥的前面,且位置不能交换,当然③和④可以交换,⑤和⑥也可以交换
// 双向循环链表插入元素
打印结果如下
![0df4429cce5341e6426bddc2294e2c83.png](https://i-blog.csdnimg.cn/blog_migrate/3d2f678d8d6c3764312ea6f060e1b55d.png)
4.双向循环链表的元素删除
删除和双向链表一样
![575830764bc72916f6cd9f6faeaab131.png](https://i-blog.csdnimg.cn/blog_migrate/64a2ebfbbcd5a694cef04e1c070e36a0.png)
①遍历需要删除节点的上一个节点得到节点p
②让p的next指向p的next的next (p.next=p.next.next),此时②1断开
③让p的next的next的prior指向p (p.next.next->p), 此时③2断开
④释放deleNode (free(deleNode))
// 双向循环链表删除结点
删除后的结果
![393c98004099a42437aac7d578c62201.png](https://i-blog.csdnimg.cn/blog_migrate/930429f16b2aa168b9830cc1dcf3853c.png)