链表详解(二)—— 带头双向循环链表

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

链表介绍

 前面说到,链表的结构一共有八种:带头单向循环链表、带头单向非循环链表、带头双向循环链表、带头双向非循环链表、无头单向循环链表、无头单向非循环链表、无头双向循环链表、无头双向非循环链表。
 在这八种结构中,我们只挑两种来进行刨析,即无头单向非循环链表和带头双向循环链表。
在这里插入图片描述
无头单向非循环链表:结构简单,一般不会用来存储数据。实际上更多是作为其他数据结构的子结构,如哈希桶、图的链接表等等。此外,这种结构在笔试面试中出现很多。
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构都是带头双向循环链表。另外,这个结构虽然复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

 在链表详解(一)中,我们已经对无头单向非循环链表进行了刨析,本篇博客主要是对带头双向循环链表进行刨析。

初始化链表

 首先,我们还是需要先定义一个结点类型,与单向链表相比,双向链表的结点类型中需要多出一个前驱指针,用于指向前面一个结点,实现双向。

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;//返回头结点
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021dragon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值