《循环双向链表》(带哨兵位的头节点)

目录

​编辑

前言:

 关于双向循环带头链表:

 模拟实现双向循环带头链表:

1.typedef数据类型

2.打印链表

3.初始化链表:

4.创建节点

5.尾插

6.头插

7.尾删

8.头删

9.寻找节点

10.在节点前插入

11.删除指定节点

单链表和双链表的区别:

链表和顺序表的区别:

对于顺序表的优势:

顺序表的问题:

链表的优势:

链表的不足:

 

总结:


前言:

我们在上一篇blog中,对于单向链表且不带哨兵位的头节点有了初步的认识,具体内容可以参考以下blog:《单链表》的实现(不含哨兵位的单向链表)-CSDN博客

今天我们将要对于双向链表的进行模拟实现,由于代码实现起来简单,并且大部分与单链表内容相似,所以我在这里我会进行过多的赘述,我们只是来讲解双向带头链表是什么,剩下的内容将是全部的代码模拟。

 关于双向循环带头链表:

简化一点就是:

 

我们会在节点里面再多定义一个指针——prev,指向上一个节点,这样方便我们进行操作。

因为有了上一个节点的地址,我们不管在尾删还是头删都可以在不保存任何节点的情况下对该节点进行操作,因此我们就会简化一系列操作。

下面将是各个模块的详细代码:

 模拟实现双向循环带头链表:

1.typedef数据类型

typedef int LTDataType;

typedef struct ListNode
{
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}LTNode;

2.打印链表

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

3.初始化链表:

LTNode* LTInit()
{
	return CreatLTNode(-1);
}

4.创建节点

LTNode* CreatLTNode(LTDataType x)
{
	LTNode* tmp = (LTNode*)malloc(sizeof(LTNode));
	if (tmp == NULL)
	{
		perror("CreatNode -> malloc");
		exit(-1);
	}
	tmp->data = x;
	tmp->next = tmp;
	tmp->prev = tmp;
	return tmp;
}

5.尾插

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = CreatLTNode(x);
	if (phead->next == phead)
	{
		phead->next = newnode;
		phead->prev = newnode;
		newnode->next = phead;
		newnode->prev = phead;
	}

	else
	{
		newnode->next = phead;
		phead->prev->next = newnode;

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

6.头插

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

7.尾删

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

8.头删

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);
	LTNode* tmp = phead->next;
	phead->next = tmp->next;
	tmp->next->prev = phead;
	free(tmp);
	tmp = NULL;
}

9.寻找节点

LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

10.在节点前插入

void ListInsert(LTNode* phead, LTNode* pos, LTDataType x)
{
	assert(pos);
    LTNode* newnode = CreatLTNode(x);
    newnode->prev = pos->prev;
	pos->prev->next = newnode;
	pos->prev = newnode;
	newnode->next = pos;
	pos->prev = newnode;
}

11.删除指定节点

void ListErase(LTNode* phead, LTNode* pos)
{
	assert(phead);
    pos->prev = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
}

单链表和双链表的区别:

对于单链表我们想要进行找尾操作,十分困难,时间复杂度为O(N)

而在双向链表中,我们想要进行找尾操作则直接利用phead->prev就可以找到尾结点,时间复杂对为O(1)。

在我们以后的面试中,如果我们的面试官对我们提出,如何在10min之内创建一个链表。

这时候我们就可以信心满满的写出双线带头循环链表,并且只需要写出ListErase 与 ListInsert即可,因为这两个函数不需要进行分类讨论。

链表和顺序表的区别:

学习了链表与顺序表,这两种均属于线性表的产物,那么我们该如何选择呢?

对于顺序表的优势:

1.支持下标的随机访问。

2.CPU高速缓存命中率较高

顺序表的问题:

1.头部或中间插入删除效率低,需要挪动数据O(N)

2.空间不够需要扩容,扩容一定要消耗,且可能存在一定的空间浪费。

3.只适合尾插尾删。

链表的优势:

1.任意位置插入删除都是O(1)。

2.按需申请释放,合理利用空间,不存在浪费

链表的不足:

  1. 随机访问性差:链表中的元素并不存储在连续的内存位置上,因此要访问链表中的任意元素需要遍历整个链表,时间复杂度为O(n)。

  2. 存储空间浪费:链表中每个节点需要额外的一个指针来指向下一个节点,这样会使链表中存储的数据量比较少,占用的存储空间较大。

  3. 插入和删除操作的效率较高:虽然插入和删除操作都是链表的优点,但是在处理大量数据时,频繁的插入和删除操作会导致链表不断地重新分配内存空间,影响性能。

  4. 不支持随机访问:链表的遍历方式只能是从头节点开始,依次访问每个节点,不能直接访问某个节点的位置。

  5. 不利于缓存:由于链表中的元素在内存中的存储位置是随机的,所以在对链表进行遍历时,缓存命中率较低,效率较差

 

总结:

以上就是我们的双向带头链表的实习,以及对于顺序表和链表之间的区别,学习完后下来可以及时整理整理,在之后我们会对顺序表和链表进行综合运用,我们将在后面实现《栈》《队列》的模拟操作,也会对于相应的题目进行分析。

记住

“坐而言不如起而行”

Action speak louder than words!

 

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

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

相关文章

【实用技巧】更改ArduinoIDE默认库文件位置,解放C盘,将Arduino15中的库文件移动到其他磁盘

本文主要介绍更改Arduino IDE &#xff08;含2.0以上版本&#xff09;默认库文件位置的方法。 原创文章&#xff0c;转载请注明出处&#xff1a; 【实用技巧】解放系统盘&#xff0c;更改ArduinoIDE默认库文件位置&#xff0c;将Arduino15中的库文件移动到其他磁盘-CSDN博客文…

2D槽道流

之前看槽道流时&#xff0c;一直无法在二维槽道流里计算出湍流状态&#xff0c;后来了解到二维槽道流需要额外添加随机扰动&#xff0c;但是这个体积力的植入方式一直不知道。而且看稳定性分析中的OS方程的推导&#xff0c;也是基于2d的NS方程&#xff0c;至今还是很疑惑这个问…

保姆级 | Nginx编译安装

0x00 前言 Nginx 是一个 HTTP 和反向代理服务器&#xff0c; 邮件代理服务器&#xff0c; 和通用 TCP/UDP 代理服务器&#xff0c; 最初由伊戈尔西索耶夫&#xff08;Igor Sysoev&#xff09;撰写。采用编译安装可以根据自身需要自定义配置&#xff0c;让服务器有更高的安全性和…

智能配电系统解决方案

智能配电系统解决方案是一种集成了先进技术和智能化功能的配电系统&#xff0c;它能够提高电力系统的效率、可靠性和安全性。力安科技智能配电系统解决方案依托电易云-智慧电力物联网&#xff0c;具体实施的方案如下&#xff1a; 智能化设备和传感器&#xff1a;采用智能化的开…

基于PI+重复控制的并网逆变系统谐波抑制策略模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; PI重复控制简介&#xff1a; 重复控制这一新型控制理论最早于出现日本学术界&#xff0c;其目的是为了用于解决质子加速器跟踪精度的问题。Yamamoto Y 等人提出了重复控制数学基础的内模原理&#xff0c;在控…

PS学习笔记——图层

文章目录 图层面板图层类型新建图层新建方式图层颜色 操作图层修改图层名称选中图层隐藏图层调整图层顺序复制图层 图层面板 按F7可打开/关闭图层面板 该面板就是图层面板了 对所有图层进行筛选的按钮&#xff0c;第一个搜索框可以选择按什么方式进行筛选&#xff0c;支持&am…

x程无忧sign逆向分析

x程无忧sign逆向分析&#xff1a; 详情页sign&#xff1a; 详情页网站&#xff1a; import base64 # 解码 result base64.b64decode(aHR0cHM6Ly9qb2JzLjUxam9iLmNvbS9ndWFuZ3pob3UvMTUxODU1MTYyLmh0bWw/cz1zb3Vfc291X3NvdWxiJnQ9MF8wJnJlcT0zODQ4NGQxMzc2Zjc4MDY2M2Y1MGY2Y…

ZHUTI主提2024春夏 聆听「宁静的声音」

将自然艺术触达生活 生活与艺术实践活动 ZHUTI主提2024春夏艺术活动「宁静的声音」&#xff0c;将自然艺术真实的触达生活为核心&#xff0c;将原野聚会、黑胶音乐、插花、咖啡、食物、舞蹈、服装等艺术与生活的元素组合在这场芦苇荡中&#xff0c;用一场兼具无穷畅想和独特审…

如何快速本地搭建悟空CRM结合内网穿透工具高效远程办公

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 无需公网IP&#xff0c;使用cpolar实现悟空CRM远程访问二. 通过公网来访问公司…

【Java】ArrayList和LinkedList使用不当,性能差距会如此之大!

文章目录 前言源码分析ArrayList基本属性初始化新增元素删除元素遍历元素 LinkedList实现类基本属性节点查询新增元素删除元素遍历元素 分析测试 前言 在面试的时候&#xff0c;经常会被问到几个问题&#xff1a; ArrayList和LinkedList的区别&#xff0c;相信大部分朋友都能回…

Intellij Idea屏蔽日志/过滤日志

一、安装插件 Grep Console 二、设置关键词&#xff0c;过滤日志 关键词的前后加上 .* 符号&#xff0c;类似&#xff1a; .*关键词.*设置后 &#xff0c;点击 Apply 即可过滤日志。

LeetCode704.二分查找及二分法

每日一题&#xff1a;LeetCode704.二分查找 LeetCode704.二分查找知识点&#xff1a;二分法解题代码 LeetCode704.二分查找 问题描述&#xff1a;给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中…

VSG-001

VulkanSceneGraph (VSG), is a modern, cross platform, high performance scene graph library built upon Vulkan VSG 是一个基于vulkan的现代的、跨平台的高性能场景管理库 VSg特性&#xff1a; 使用C17作为c规范编码&#xff0c;支持 CppCoreGuidelines支持 FOSS Best P…

大师学SwiftUI第16章 - UIKit框架集成

其它相关内容请见​​虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记​​ SwiftUI是一套新框架&#xff0c;因此并没有包含我们构建专业应用所需的所有工具。这意味着我们会需要求助于UIKit&#xff08;移动设备&#xff09;和AppKit&#xff08;Mac电脑&#xff09;等原…

optee4.0.0 qemu_v8的环境搭建篇(ubuntu20.10)

快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】:【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈文章目录 前提条件1、拉取代码2、下载工具链3、编译4、运行

Unity在Windows选项下没有Auto Streaming

Unity在Windows选项下没有Auto Streaming Unity Auto Streaming插件按网上说的不太好使最终解决方案 Unity Auto Streaming插件 我用的版本是个人版免费版&#xff0c;版本号是&#xff1a;2021.2.5f1c1&#xff0c;我的里边Windows下看不到Auto Streaming选项,就像下边这张图…

一起Talk Android吧(第五百五十三回:解析Retrofit返回的数据)

文章目录 1. 知识回顾2. 解析方法2.1 解析有效数据2.2 解析错误数据3. 示例代码4. 经验与总结4.1 经验分享4.2 内容总结各位看官们大家好,上一回中咱们说的例子是"Retrofit的基本用法",本章回中介绍的例子是" 如何解析Retrofit返回的数据"。闲话休提,言…

【南京】最新ChatGPT/GPT4科研技术应用与AI绘图及论文高效写作

2023年我们进入了AI2.0时代。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车&#xff0c;就有可能被淘汰在这个数字化时代&#xff0c;如何能高效地处理文本、文献查阅、PPT…

深入了解Java 8 新特性:lambda表达式基础

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概000多字&#xff0c;预计阅读时间长需要5分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&#xf…

数据库选型与优化:策略与技巧的探讨

大家好&#xff0c;我是一名狂热的数据库程序员&#xff0c;最近鼓起勇气开始吐槽一下数据库&#xff0c;如有雷同&#xff0c;请对号入座。 名不副实的数据库类型 先说说最近的事&#xff0c;我们业务有很多图片要管理&#xff0c;老板说让我选个专业的图数据库&#xff0c;…