【数据结构】双向链表

在这里插入图片描述

🚀write in front🚀
📜所属专栏: 初阶数据结构
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

前言

  在前面的博客中,我们学习了单链表的实现与操作。然而单链表在进行找尾等操作时,会导致时间复杂度很低。下面我来介绍一下双向链表的相关知识。

一.双向循环链表的实现

  由下面的图我们可以看出,双向链表在创建时会建立两个指针,此时链表就不仅可以往后链接,还可以向前链接。
在这里插入图片描述

我们来看看他们的区别:

  • 之前写的单链表是没有头节点的,但是双向循环链表是有头节点的
  • 双向循环链表的头和尾也要建立联系,这样就可以快速找尾

  因为之前写过单链表,下面我们就快速的实现双链表了,不细细介绍了。

创建新节点:

LTNode* BuyListNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc::newnode");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;
	return newnode;
}

创建返回链表的头结点.

LTNode* LTInit()
{
	LTNode* newnode = BuyListNode(-1);
	newnode->next = newnode;
	newnode->prev = newnode;

	return newnode;
}

  该头节点在初始化说要自行成环,方便后面拼接。

打印链表

void LTPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur!=phead)
	{
		printf("%d<==>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

判断链表是否只有头节点

bool LTEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead;
}

  这个判断十分重要,因为只剩头节点的话就不能删除了。

双向链表尾插

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = BuyListNode(x);

	LTNode* tail = phead->prev;
	tail->next = newnode;
	newnode->next = phead;
	newnode->prev = tail;
	phead->prev = newnode;
}

双向链表尾删

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty);
	LTNode* tail = phead->prev;
	tail->prev->next = phead;
	phead->prev = tail->prev;
	free(tail);
	tail = NULL;
}

  删除了要记得和头节点重新形成联系。

双向链表头插

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = BuyListNode(x);
	LTNode* first = phead->next;
	phead->next = newnode;
	newnode->next = first;
	newnode->prev = phead;
	first->prev = newnode;
}

在pos位置后面插入

void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyListNode(x);
	LTNode* cur = pos->next;
	pos->next = newnode;
	newnode->prev = pos;
	newnode->next = cur;
	cur->prev = newnode;
}

二.顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持,O(1)不支持,O(N)
任意位置插入或者删除可能需要搬移元素,效率低O(N)只需修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

总结

  这就是今天对双向循环链表的简要介绍,对于链表的学习就先告一段落了,接下来我们将开始学习栈与队列的知识了!

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
c语言学习
算法
智力题
初阶数据结构
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

  • 32
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 28
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小参宿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值