链表介绍
前面说到,链表的结构一共有八种:带头单向循环链表、带头单向非循环链表、带头双向循环链表、带头双向非循环链表、无头单向循环链表、无头单向非循环链表、无头双向循环链表、无头双向非循环链表。
在这八种结构中,我们只挑两种来进行刨析,即无头单向非循环链表和带头双向循环链表。

无头单向非循环链表:结构简单,一般不会用来存储数据。实际上更多是作为其他数据结构的子结构,如哈希桶、图的链接表等等。此外,这种结构在笔试面试中出现很多。
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构都是带头双向循环链表。另外,这个结构虽然复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。
在链表详解(一)中,我们已经对无头单向非循环链表进行了刨析,本篇博客主要是对带头双向循环链表进行刨析。
初始化链表
首先,我们还是需要先定义一个结点类型,与单向链表相比,双向链表的结点类型中需要多出一个前驱指针,用于指向前面一个结点,实现双向。
typedef int LTDataType;//存储的数据类型
typedef struct ListNode
{
LTDataType data;//数据域
struct ListNode* prev;//前驱指针
struct ListNode* next;//后继指针
}ListNode;
然后我们需要一个初始化函数,对双向链表进行初始化,在初始化的过程中,需要申请一个头结点,头结点的前驱和后继指针都指向自己,使得链表一开始便满足循环。

//创建一个新结点
ListNode* BuyListNode(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL)
{
printf("malloc fail\n");
exit(-1);
}
node->data = x;//新结点赋值
node->prev = NULL;
node->next = NULL;
return node;//返回新结点
}
//初始化链表
ListNode* ListInit()
{
ListNode* phead = BuyListNode(-1);//申请一个头结点,头结点不存储有效数据
//起始时只有头结点,让它的前驱和后继都指向自己
phead->prev = phead;
phead->next = phead;
return phead;//返回头结点
深度解析:带头双向循环链表操作与管理

本文详细讲解了如何初始化、销毁、打印带头双向循环链表,包括查找元素、增加、删除节点以及链表的判空和元素个数计数。重点介绍了头插、尾插和指定位置插入的操作技巧。
最低0.47元/天 解锁文章
1555





