【数据结构】第四讲:双向链表

目录

一、链表的分类

二、双向链表的结构及实现

1.带头双向链表的结构

2.创建节点

3.初始化

4.尾插

5.打印

6.头插

7.尾删

8.头删

9.在pos位置之后插入数据

10.删除pos节点

11.查找

12.销毁


个人主页:深情秋刀鱼@-CSDN博客

数据结构专栏:数据结构与算法

        循环链表这个轮回的思想很有意思。它强调了不管你今生是贫是富,如果持续行善积德,下辈子就会好过,反之就会遭到报应。

        就像每个人的人生一样,欲收获就得付出代价。双向链表既然是比单链表多了如可以反向遍历查找的数据结构,那么也就要付出一些小的代价。

一、链表的分类

        链表的结构复杂多样,总计有如下八种形式。

        虽然有这么多的链表的结构,但是我们实际中最常⽤还是两种结构: 单链表 双向带头循环链表。
1. ⽆头单向⾮循环链表:结构简单,⼀般不会单独⽤来存数据。实际中更多是作为其他数据结 构的⼦结构,如哈希桶、图的邻接表等等。另外这种结构在笔试⾯试中出现很多。
2. 带头双向循环链表:结构最复杂,⼀般⽤在单独存储数据。实际中使⽤的链表数据结构,都 是带头双向循环链表。另外这个结构虽然结构复杂,但是使⽤代码实现以        后会发现结构会带 来很多优势,实现反⽽简单了。

       

二、双向链表的结构及实现

1.带头双向链表的结构

         对于带头和不带头,在学习单链表是我们将其理解为链表的头节点(链表的第一个节点),这种称呼很不严谨,在本节中的带头和不带头指的是在该链表中书否含有哨兵结点,哨兵结点在双向链表中是名副其实的头节点,哨兵节点内不存储任何有效的数据,他的唯一作用是防止在遍历链表时进入死循环。

//双向链表的定义
typedef int LTDataType;

//定义双向链表的节点
typedef struct ListNode
{
	LTDataType data;//数据域
	struct ListNode* next;//指向后继节点的指针
	struct ListNode* prev;//指向前驱节点的指针
}ListNode;

2.创建节点

ListNode* LTbuyNode(LTDataType x)
{
	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	if (newNode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newNode->data = x;
	newNode->next = newNode;
	newNode->prev = newNode;//创建的新节点指向自身
	return newNode;
}

3.初始化

//初始化
void LTinit(ListNode** pphead)
{
	*pphead = LTbuyNode(-1);//哨兵位(不存储有效值)
}

4.尾插

//尾插
void LTpushBack(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* node = LTbuyNode(x);
	node->prev = phead->prev;
	node->next = phead;
	phead->prev->next = node;
	phead->prev = node;
}

5.打印

//打印
void LTprint(ListNode* phead)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("head\n");
}

6.头插

//头插
void LTpushFront(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* node = LTbuyNode(x);
	node->prev = phead;
	node->next = phead->next;
	phead->next->prev = node;
	phead->next = node;
}

7.尾删

//尾删
void LTpopBack(ListNode* phead)
{
	assert(phead && phead->next != phead);//链表不为空
	ListNode* pcur = phead->prev;
	phead->prev->prev->next = phead;
	phead->prev = phead->prev->prev;
	free(pcur);
	pcur = NULL;
}

8.头删

//头删
void LTpopFront(ListNode* phead)
{
	assert(phead && phead->next != phead);
	ListNode* pcur = phead->next;
	phead->next->next->prev = phead;
	phead->next = phead->next->next;
	free(pcur);
	pcur = NULL;
}

9.在pos位置之后插入数据

//pos位置之后插入数据
void LTinsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* node = LTbuyNode(x);
	pos->next->prev = node;
	node->prev = pos;
	node->next = pos->next;
	pos->next = node;
}

10.删除pos节点

//删除pos节点
void LTerase(ListNode* pos)
{
	assert(pos);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
	pos = NULL;
}

11.查找

//查找
ListNode* LTfind(ListNode* phead, LTDataType x)
{
	assert(phead && phead->next != phead);
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x)
		{
			printf("找到了!\n");
			return pcur;
		}
		pcur = pcur->next;
	}
	printf("没有找到!\n");
	return NULL;
}

12.销毁

//销毁
void LTdestroy(ListNode* phead)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		ListNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	free(phead);
	phead = NULL;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mac M2 本地下载 Xinference

想要在Mac M2 上部署一个本地的模型。看到了Xinference 这个工具 一、Xorbits Inference 是什么 Xorbits Inference(Xinference)是一个性能强大且功能全面的分布式推理框架。可用于大语言模型(LLM),语音识别模型&…

激动,五四青年节,拿下YashanDB认证YCP

📢📢📢📣📣📣 作者:IT邦德 中国DBA联盟(ACDU)成员,10余年DBA工作经验, Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主,全网粉丝10万 擅长主流Oracle、My…

中间件之搜索和数据分析组件Elasticsearch

一、概述 1.1介绍 The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。 能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视 化。Elaticsearch,简称为 ES&a…

CUDA和显卡驱动

1.安装显卡驱动 https://www.nvidia.com/download/index.aspx?langen-us 由于我的显卡是RTX4060,因此先选择RTX40系列,然后选择RTX4060,进行安装 2.查看显卡对应的CUDA CUDA安装地址:https://developer.nvidia.com/cuda-toolk…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-12-蜂鸣器

前言: 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

复旦微JFM7VX690计算后IO接口模块,用于雷达信号处理、数据处理等需要高速密集计算的应用场景

计算后IO接口模块 1 介绍 1.1 产品概述 计算后IO接口模块主要由复旦微JFM7VX690型FPGA、国产以太网收发器YT8521、国产BMC芯片GD32F450、国产CPLD芯片EF2L45BG256B、国产内存颗粒等主要芯片组成,采用标准6U VPX尺寸设计。 本计算后IO接口模块主要用于雷达信号处…

QT+串口调试助手+基本版

一、创建串口调试助手UI界面 1、首先生成串口连接必要参数界面,删除关闭串口控件 2、给参数下拉框添加常见的选项,删除关闭串口控件 3、将串口调试助手参数界面布局整齐,删除关闭串口控件 4、更改控件名字,方便后续编程&#xff…

第五篇:通信脉络:探索计算机外设与总线体系的精髓

通信脉络:探索计算机外设与总线体系的精髓 1 引言 在这个技术日新月异的时代,理解计算机系统的基本构成要素 —— 总线和外设 —— 对于每个从事技术工作的人来说都是至关重要的。这些组件不仅是计算机通信的基石,也直接影响着系统的性能、效…

Universal Thresholdizer:将多种密码学原语门限化

参考文献: [LS90] Lapidot D, Shamir A. Publicly verifiable non-interactive zero-knowledge proofs[C]//Advances in Cryptology-CRYPTO’90: Proceedings 10. Springer Berlin Heidelberg, 1991: 353-365.[Shoup00] Shoup V. Practical threshold signatures[C…

关于MS-DOS时代的回忆

目录 一、MS-DOS是什么? 二、MS-DOS的主要功能有哪些? 三、MS-DOS的怎么运行的? 四、微软开源MS-DOS源代码 五、高手与漂亮女同学 一、MS-DOS是什么? MS-DOS(Microsoft Disk Operating System)是微软公…

多线程与信号量简介

信号量与 PV 操作 计算机中信号量的本质是整数,数值表示可用的资源数量 P 操作 (Passeren > 通过, 原子操作) 若信号量 0,当前任务阻塞 (进入信号量等待队列)若信号量 > 0,则:将信号量数值减一,当前任务继续执…

USP技术提升大语言模型的零样本学习能力

大语言模型(LLMs)在零样本和少样本学习能力上取得了显著进展,这通常通过上下文学习(in-context learning, ICL)和提示(prompting)来实现。然而,零样本性能通常较弱,因为缺…

KMP算法--C语言实现

#include <stdio.h> #include <assert.h> #include <string.h> #include <stdlib.h>void GetNext(char* sub, int next[]) {int lenSub strlen(sub);next[0] -1; // 初始第一个为 -1 第二个为 0next[1] 0;int i 2;int k 0;while (i < lenSub){…

探究Android的多分辨率支持以及各种类型图标尺寸大小

术语和概念 屏幕尺寸 屏幕的物理尺寸&#xff0c;以屏幕的对角线长度作为依据&#xff08;比如 2.8寸&#xff0c; 3.5寸&#xff09;。 简而言之&#xff0c; Android把所有的屏幕尺寸简化为三大类&#xff1a;大&#xff0c;正常&#xff0c;和小。 程序可以针对这三种尺寸…

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例 引言1. UniMRCP和UmcFramework简介2. 准备工作3. unimrcpclient.xml配置文件3.1 定义SIP设置3.2 定义MRCP会话配置文件 4. C代码示例5. 测试和验证6. 故障排查7. 结论8. 参考文献 引言 在多媒体通信…

Vue单页面应用和多页面应用的区别

概念&#xff1a; SPA单页面应用&#xff08;SinglePage Web Application&#xff09;&#xff0c;指只有一个主页面的应用&#xff0c;一开始只需要加载一次js、css等相关资源。所有内容都包含在主页面&#xff0c;对每一个功能模块组件化。单页应用跳转&#xff0c;就是切换…

STM32标准库编译流程

导入库函数 在ST官方固件库中找到STM32F10x_StdPeriph_Lib_V3.5.0.zip文件&#xff0c;解压&#xff0c;打开Libraries,接着打开STM32F10x_StdPeriph_Driver文件夹&#xff0c;继续点击src&#xff0c;看到库函数源文件&#xff1a; 将其复制到keil建立的工程的文件中&#xf…

JAVA系列 小白入门参考资料 接口

目录 接口 接口的概念 语法 接口使用 接口实现用例 接口特性 实现多个接口和实现用例 接口间的继承 接口 接口的概念 在现实生活中&#xff0c;接口的例子比比皆是&#xff0c;比如&#xff1a;笔记本上的 USB 口&#xff0c;电源插座等。 电脑的 USB 口上&am…

在视频中使用时间卷积和半监督训练进行三维人体姿态估计

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;在视频中使用时间卷积和半监督训练进行三维人体姿态估计1、文献摘要2、提出方法2.1、时间扩张卷积模型2.2、半监督方法2.3、与传统…

【错题集-编程题】十字爆破(预处理 + 模拟)

牛客对于题目链接&#xff1a;十字爆破 (nowcoder.com) 一、分析题目 暴力模拟会超时。 预处理&#xff0c;先把每一行以及每一列的和存起来。 模拟即可&#xff0c;但是由于数据量过⼤&#xff0c;我们可以提前把每⼀⾏以及每⼀列的和存起来&#xff0c;⽅便统计总和。 二、代…