用C语言实现一个链表(三)
在前两期内容中,我们探讨了不带哨兵位头结点单链表的C语言实现,而链表有很多种,本期讨论的是另一种非常重要的结构——带头双向循环链表。
一、准备工作
1.何为双向循环链表(带有头结点)
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前一个结点和后一个结点。一般我们都构造双向循环链表,也就是将最后一个数据结点指向头结点,将头结点的前驱指针指向最后一个结点。
2.实现一个双向循环链表,我们需要些什么?
(1)data
data是指节点存储的数据,称为结点的数据域,其类型通过typedef来灵活定义。
(2)指针
结点除了存放数据之外,还要留有指向下一个结点和上一个结点的指针,称为指针域。指向上一个结点的指针命名为prev,指向下一个结点的指针命名为next。
(3)结构体
一个结点中包含数据域和指针域,我们可以将它们放入一个结构体中,如图:
二、双向循环链表的实现(代码+分析)
这次我们所要实现的是带有头结点的双向循环链表,所谓哨兵位头结点,就是不存储数据的结点,有了这样的一个头结点,在操作过程中,只要向函数传递头结点的地址即可,不需要传二级指针。因为我们在操作过程中改变的是结构体内部的内容,这是和上期不带头的单链表实现是有明显的区别的,在接下来的代码实现中,我们可以逐渐体会到这一点。
1.创建新结点
和单链表类似,函数的返回值是一个结构体指针,代码如下:
DCLLNode* CreateDCLLNode(DataType x)
{
DCLLNode* node = (DCLLNode*)malloc(sizeof(DCLLNode));//创建一个新结点
if (node == NULL)//判断动态内存开辟是否成功
{
perror("malloc fail");
return NULL;