数据结构【链表】看完还怕拿不下链表?

news2024/12/24 7:49:40

在这里插入图片描述

✨Blog:🥰不会敲代码的小张:)🥰
🉑推荐专栏:C语言🤪、Cpp😶‍🌫️、数据结构初阶💀
💽座右铭:“記住,每一天都是一個新的開始😁😁😁

前言

上一章节:无头单向非循环链表

具体链表介绍内容请见上一章节
本章节主要介绍双向链表以及带头节点和循环的概念和实现,并且本章是在上一章节的基础上加以改造,虽然结构复杂了点,但是要比单链表更好实现🤪

目录

  • 前言
  • 双链表介绍
  • 链表的创建
  • 创建新节点
  • 初始化头节点
  • 销毁链表结点
  • 打印链表
  • 判断链表是否为空
  • 尾插
  • 尾删
  • 头插
  • 头删
  • 在pos的前一个位置插入
  • 删除pos位置节点
  • 查找

双链表介绍

在这里插入图片描述
从上面的图中我们可以看到,每一个节点都会有一个指针指向前一个和后一个,然后头节点指向最后一个节点,最后一个节点指向头节点,这就是带头双向循环链表。
那为什么会有单链表和双链表之分呢?
在单链表删除或者查询一个元素时,我们只能单向读取,然后如果删除的话,我们要保存前一个节点,为克服单链表的单向性,可以使用双链表更好的解决此问题。
头结点是为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等)

链表的创建

prev指针指向前一个,next指针指向后一个

typedef int LDataType;
typedef struct ListNode
{
	LDataType data;
	struct ListNode* prev;
	struct ListNode* next;

}ListNode;

创建新节点

//创建新的节点
ListNode* BuyListNode(LDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("BuyListNode");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;

	return newnode;
}

初始化头节点

最开始的头节点前后指针都指向自己,如果有元素插入进来再更改指针指向的位置
在这里插入图片描述

//初始化头节点
ListNode* LsitInit()
{
	ListNode* phead = BuyListNode(-1);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

销毁链表结点

把头节点的后一个的节点给cur指针,也就是第一个节点的位置
cur指针指向头节点的时候,以及遍历完了链表,所以循环不再进去
然后保留cur的下一个节点,free掉cur,再把next给cur,继续向后走
在这里插入图片描述

//销毁节点
void ListDestroy(ListNode* phead)
{
	assert(phead);//断言phead不能为空
	ListNode* cur = phead->next;//头节点的下一个才是第一个元素
	while (cur != phead)//cur的next不能等于头节点
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

打印链表

//打印节点数据
void ListPrint(ListNode* phead)
{
	assert(phead);
	ListNode* cur = phead->next;

	printf("head<=>");

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

判断链表是否为空

如果头节点的next指针指向自己,说明链表为空

bool ListEmpty(ListNode* phead)
{
	assert(phead);
	return phead->next == phead;
}

尾插

只需要更改指针关系,找到最后一个节点的位置,在尾部链接要插入的节点,把新插入的节点前指针和后指针链接到对应的位置即可
在这里插入图片描述

//尾插
void ListPushback(ListNode* phead, LDataType x)
{
	assert(phead);

	ListNode* newnode = BuyListNode(x);
	ListNode* tail = phead->prev;

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

尾删

找到最后一个节点tail,保留tail的前一个tailprev
把tailprev的next指向头节点,头节点的prev指向tailprev
在这里插入图片描述

//尾删
void ListPopback(ListNode* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));

	ListNode* tail = phead->prev;
	ListNode* tailprev = tail->prev;
	
	tailprev->next = phead;
	phead->prev = tailprev;
	free(tail);
	tail = NULL;
}

头插

更改指针关系的时候一定要注意先后顺序,不然一旦指针更改可能就会链接到错误的地方
在这里插入图片描述

void ListPushFront(ListNode* phead, LDataType x)
{
	assert(phead);
	ListNode* newnode = BuyListNode(x);
	
	newnode->next = phead->next;
	phead->next->prev = newnode;
	newnode->prev = phead;
	phead->next = newnode;

	//ListInsert(phead->next, x);
}

头删

注意:只要是删除链表节点,就要判断链表是否为空,如果为空就直接报错
tail指针指向第一个节点,让头节点指针指向tail的next
tail的next的prev指向头节点
最后free掉tail指向的节点
在这里插入图片描述

//头删
void ListPopFront(ListNode* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));

	ListNode* tail = phead->next;
	phead->next = tail->next;
	tail->next->prev = phead;
	free(tail);
	tail = NULL;

	//ListErase(phead->next);

}

在pos的前一个位置插入

注:pos要配合着查找函数一起使用,比如查找6,找到之后返回6的地址给指针。
记录pos前一个的节点,然后再更改指针之间的关系
在这里插入图片描述

//在pos的前一个位置插入
void ListInsert(ListNode* pos, LDataType x)
{
	assert(pos);
	ListNode* newnode = BuyListNode(x);
	ListNode* prev = pos->prev;

	pos->prev = newnode;
	newnode->next = pos;
	prev->next = newnode;
	newnode->prev = prev;
}

删除pos位置节点

在这里插入图片描述

//删除pos位置节点
void ListErase(ListNode* pos)
{
	assert(pos);
	assert(!ListEmpty(pos));

	ListNode* prev = pos->prev;

	prev->next = pos->next;
	pos->next->prev = prev;
	free(pos);
	pos = NULL;
}

查找

定义一个cur指针指向第一个节点,如果cur的data和要查找的值一样就返回cur,如果不想等就让cur向后走,直到cur走到头节点循环结束。

//查找
ListNode* ListFind(ListNode* phead, LDataType x)
{
	assert(phead);

	ListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data != x)
			cur = cur->next;
		else
			return cur;
	}
	return NULL;
}

创作不易,记得三连!笔者水平有限,如有错误的地方,还望指出,谢谢大家😋😋😋

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/572001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐5款提高生活和工作效率的好帮手

在这个数字化时代,软件工具已经深深地影响和改变了我们的生活和工作。有着各种各样的软件工具,它们都可以在特定的领域内让我们变得更加高效,完成复杂的任务。选择一款适合你的软件工具,不但可以极大地释放生产力,也可以让生活变得更加便捷。 1.桌面图标管理工具——TileIconi…

阿里开源!集成了 AIGC 的免费数据库工具:Chat2DB

今天推荐的这个项目是「Chat2DB」&#xff0c;一款开源免费的数据库客户端工具&#xff0c;支持 Windows、Mac 本地安装&#xff0c;也支持服务器端部署&#xff0c;Web 网页访问。 和传统的数据库客户端软件 Navicat、DBeaver 相比 Chat2DB 集成了 AIGC 的能力&#xff0c;能…

基于LLMs的多模态大模型(PALM-E,ArtGPT-4,VPGTrans )

这个系列已经更文一些了&#xff0c;如果有新的文章会继续补充&#xff1a; 基于LLMs的多模态大模型&#xff08;Visual ChatGPT&#xff0c;PICa&#xff0c;MM-REACT&#xff0c;MAGIC&#xff09;基于LLMs的多模态大模型&#xff08;Flamingo, BLIP-2&#xff0c;KOSMOS-1&…

2023年DAMA-CDGA/CDGP认证合肥/厦门/长春/深圳可以报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

【MySQL】实验十 E-R图

文章目录 1. 学校2. 院系3. 图书馆4. 舰队5. 工厂6. 网购7. 公司1. 学校 设有如下实体: 班主任:工号、姓名、电话 班级:班号、专业、毕业总学分 学生:学号、姓名、性别、年龄 课程:课程号、课程名 上述实体中存在如下联系: (1)一个班主任管理一个班级,一个班级由一个…

小兔鲜--项目总结 2

目录 登录-表单校验实现 表单如何进行校验 表单校验步骤 自定义校验规则 整个表单的内容验证 登录-基础登录业务实现 登录业务流程 Pinia管理用户数据 如何使用Pinia管理数据 关键代码总结 登录-Pinia用户数据持久化 持久化用户数据说明 ​编辑关键步骤总结和插件运行机…

基于 JMeter 实现 WEB 项目性能测试,环境搭建与测试用例编写

目录 前言&#xff1a; 一、JDK 安装 二、Tomcat 安装 三、Redis 安装 四、数据库安装 五、WEB 项目搭建 六、性能测试项目搭建 七、总结 前言&#xff1a; 性能测试是软件开发中必不可少的一环&#xff0c;它可以帮助开发者提高程序的稳定性&#xff0c;优化性能&…

【产品经理】产品体验报告的思路

&#xff08;一&#xff09;产品概述 &#xff08;1&#xff09;体验环境 对于app来说&#xff0c;无非就是体验产品所用的机型&#xff0c;系统&#xff0c;然后app版本&#xff0c;体验时间&#xff0c;体验人等方面的信息。 &#xff08;2&#xff09;产品的概括或简介说…

基于LLMs的多模态大模型(Visual ChatGPT,PICa,MM-REACT,MAGIC)

当LLMs已经拥有了极强的对话能力后&#xff0c;如何使其拥有视觉和语音等多模态能力是紧接而来的热点&#xff08;虽然GPT4已经有了&#xff09;&#xff0c;这个系列将不定期更新一些利用LLMs做多模态任务的文章。 直觉上&#xff0c;如果直接训练一个类似chatgpt架构的多模态…

7种PCB走线方式

01电源布局布线相关 数字电路很多时候需要的电流是不连续的&#xff0c;所以对一些高速器件就会产生浪涌电流。 如果电源走线很长&#xff0c;则由于浪涌电流的存在进而会导致高频噪声&#xff0c;而此高频噪声会引入到其他信号中去。 而在高速电路中必然会存在寄生电感和寄…

SSM 如何使用 ShardingSphere 实现数据库分库分表

SSM 如何使用 ShardingSphere 实现数据库分库分表 简介 在大规模数据应用场景下&#xff0c;单一数据库可能无法承载高并发的读写操作。为了解决这个问题&#xff0c;一种常见的方式是使用数据库分库分表技术。ShardingSphere 是一个支持多种关系型数据库的分布式数据库中间件…

带您看懂全国产串口服务器!如何使用一看便知

不可否认&#xff0c;目前工业现场仍然会有很多串口设备的存在&#xff0c;对于这些串口设备&#xff0c;如果想要联网&#xff0c;就必须要转换成网络接口&#xff0c;这时候就会用到全国产串口服务器。 全国产串口服务器提供串口转网络功能&#xff0c;能够将RS-232/485/422串…

盐城北大青鸟“北大青鸟杯”IT精英挑战赛设中心评审隆重开赛

为积极响应北大青鸟总部开展第十届“北大青鸟杯”全国IT精英挑战赛的号召&#xff0c;成就学员们的IT梦想&#xff0c;“北大青鸟杯”IT精英挑战赛&#xff08;设计组&#xff09;盐城卓晨中心评审于2023年5月25日下午1:00在人才大厦306教室正式开赛&#xff01; ​ 赛前&a…

【状态估计】基于随机方法优化PMU优化配置(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

报表控件FastReport使用指南——使用NuGet包创建PDF文档

FastReport 是功能齐全的报表控件&#xff0c;可以帮助开发者可以快速并高效地为.NET&#xff0c;VCL&#xff0c;COM&#xff0c;ActiveX应用程序添加报表支持&#xff0c;由于其独特的编程原则&#xff0c;现在已经成为了Delphi平台最优秀的报表控件&#xff0c;支持将编程开…

低代码平台简介(10家国产化低代码平台详细介绍)

低代码平台&#xff1a;一个号称能在几分钟的时间里开发一套企业内部都可使用的系统开发工具。 本人曾做过一个测试&#xff0c;2人&#xff0c;历时8小时&#xff0c;用低代码平台成功搭建出一套“客户管理系统”。该系统所需要的15个子模块与40个界面。同样的功能如果用传统编…

什么是 sudo,为什么它如此重要?

在当今的技术世界中&#xff0c;Linux 操作系统广泛应用于各种环境&#xff0c;包括个人计算机、服务器和嵌入式设备。作为一种强大的开源操作系统&#xff0c;Linux 提供了丰富的安全功能&#xff0c;以保护系统和用户的数据安全。在 Linux 安全领域中&#xff0c;sudo 是一项…

接口测试的请求和响应

接口测试的请求和响应 在软件开发中&#xff0c;接口测试是必不可少的一环节。接口测试主要涉及到测试请求和响应的过程。请求是指客户端向服务器发送的一些指令或数据&#xff0c;而响应则是服务器对这些请求做出的回应。 请求通常包括请求方法、请求头以及请求体。请求方法有…

信息安全服务资质认证CCRC证书‖中国网络安全审查技术与认证中心

随着CCRC信息安全服务资质持证企业的增加&#xff0c;很多企业看着自己的同行纷纷获的CCRC证书&#xff0c;自身也想进行申报&#xff0c;但由于之前没有做过了解&#xff0c;像个无头苍蝇一样&#xff0c;所以对该资质申报的条件要求、申报的好处又不是那么清楚&#xff0c;接…

重塑DeFi:深入了解Solaris Network

Solaris Network已经在充满活力的去中心化金融&#xff08;DeFi&#xff09;领域崭露头角&#xff0c;成为一家颠覆性的平台&#xff0c;使用户能够创造和交易合成资产。凭借其致力于多链集成、创新功能和以社区为中心的方法&#xff0c;Solaris Network正在改变DeFi的格局&…