数据结构之链表深度讲解

小伙伴们,大家好呀,上次听我讲完顺序表想必收获不少吧,嘿嘿,这篇文章你也一样可以学到很多,系好安全带,咱们要发车了。

因为有了上一次顺序表的基础,所以这次我们直接进入正题,温馨提示:本篇文章的内容会比上次的顺序表文章的内容更加难,所以请耐心看完,过程中我会将一些难点,易混淆点给大家一一细讲,如有需要自行做笔记。


链表结构体内的元素

和顺序表里一样创建一个自定义类型的结构体,并且创建一个自定义类型的变量,以及指向下一个节点的指针next。

链表的尾插

链表和上次的顺序表一样也有尾插,那么我先教大家在链表头文件里如何写这个函数。也许会有小伙伴说函数不是很简单吗,而且看了博主这么多的文章,写个函数有何难呢。其实事情不是你想的那么简单,且听我细细道来。

首先,我们先来看一下两张图的区别

顺序表在测试文件中的尾插函数

链表在测试文件中的尾插函数

从图中我们可以看到俩图的区别

相同点:尾插时都是传了地址和要插入的数据

不同点:创建时,顺序表:结构体缩名   表名         链表:用指针的形式定义第一个节点   

那么这时我们也就可以在链表头文件内写尾插函数了,代码如下:

也许这时就会有人懵了,诶,我当时只是传了节点的地址呀,怎么这里就突然用了二级指针了?

所以说,话可不能说得太满。

之前我就已经详细的介绍了,我们在创建第一个节点时是以指针的形式创建,现在又传地址(也就是说传的是指针的地址)给尾插函数,所以这里就应该用二级指针啦。

那么基本上就给大家讲清楚啦,这是本篇文章的第一个难点

那么接下来我们来看看尾插代码主体部分具体怎么写吧。

思路:和顺序表一样先判断是否为空,因为我们创建好的第一个节点是空的,因此我们要去给它申请空间(这个函数具体怎么写放在下面,一会儿会简单讲一下),然后判断第一个节点是否为空,如果第一个节点为空,那么直接用“=”插入即可。温馨提醒:指针   =   指针的意思就是与变量与变量之间的赋值是一样的。那么当二级指针不为空时,我们需要以指针的形式创建尾节点,并且规定尾节点指向下一个的节点的地址不为空,也就是while(ptail->next),让ptail指针遍历链表,链表为空时插入数据。其中patil   =   ptail->next   的意思是ptail这个指针已经移到了下一个节点处, 那么   ptail->next   =    newnode  意思就是ptail指针连接到了newnode这个节点,但指针ptail还未移动到newnode处。为了方便大家理解,可以看一下下面的图

简单地给大家画了一下,差不多就这个意思,希望大家能理解。

那么尾插函数已经介绍完了,我们再来简单过一下链表中如何申请空间。

链表中申请节点空间

基本上和顺序表的差不太多,不一样的地方有顺序表里使用的是realloc(增容),而我们这里需要的是申请空间,因此我们可以用malloc,也可以使用calloc,大家有兴趣可以自己去尝试一下。申请完空间后,也许有人就不知道该干什么了,兄台别忘了我们是要把这个数据给尾插进去的呀,因此就得到了newnode->data =  x,插入完毕后也不要忘记将next指针置为空哦。

那么到此为止我们的链表尾插算是真正讲完了。尾插讲完后,我们就要开始起飞了,请各位小伙伴们系好安全带,飞机即将起飞。

链表的头插

链表头文件里的头插函数和上面图片里的一样,这里就不浪费文字去讲解了。毕竟我们主要还是将链表源文件的头插函数内部的写法和思路,首先我们来思考一个问题:假设我们就往一个空链表中进行插入数据,那么请问这个数据的插入方式究竟是头插还是尾插?想必大家的答案都是无法确定该数据的插入方式。因此我们可以从这里得到一个结论:头插数据时必须确保链表不为空,那么我们就可以确定这个函数上来就可以先给它断言:链表不为空。紧接着我们来看一下下面这张图

大家可以看到:这是一个不为空的链表,此时我们要头插数据,但是前面没有节点,因此我们需要创建节点,并且插入数据,因此也就有了代码图中的第二行代码,并且让newnode的next指针指向下一个节点,也就是我们在创建新节点之前的头节点pphead,并且此时pphead已经不再是头节点了,因此,我们需要用赋值符号“=”将pphead移到前面去(换句话说就是将两个指针互换了一下位置,但我不推荐这么理解)。

学习指南:看到这里的小伙伴如果感觉还吃得消,那么请继续看头插与尾插的拓展,如果有吃不消的小伙伴,可以先下滑看链表的尾删。

头插与尾插的拓展

指定位置的尾插

首先,我们需要确保所指定的位置不能为空,其次节点与节点之间没有空间,如图所示

因此我们需要使用malloc申请空间,创建新节点

创建完新的节点之后我们就要将其与其他节点连接起来,那么我们先连newnode的尾部吧,我们需要将newnode->next 指向原先pos所指向的下一个位置,也就是newnode->next   =    pos->next, newnode的前面就是与pos相连接即可,也就是让pos->next指向newnode

指定位置的头插

首先,我们需要确保链表不为空,并且头节点也不为空(为什么不能为空,一会给大家解释),对于我们来说最容易想到的是第二种情况

思路:我们需要定义一个新的指针使该指针从头节点phead开始,当prev的下一个节点是pos时,停下,并头插newnode这个节点。

第一种思路往往是我们容易忽略的一种

这种情况,我们只需要使用if语句,条件就是pos == phead即可,之后再调用一下我们指前写的头插函数将该数据插入就完成了,所以不明白*phead不能为空的小伙伴们恍然大悟了吗?

那么如何找到指定位置呢?

思路:我们先重新定义一个头节点pcur,通过循环找到与x相等的节点并返回即可

指定位置的删除

首先保证链表头节点和指定位置不为空,那么这里我们分两种情况讨论:

第一种:当指定位置就是头节点时,直接调用头删函数

第二种:也就是如下图这种情况时

先找到pos的前一个节点,让它的next指向pos的下一个节点,如图

最后就是释放掉pos并且置为空即可

指定位置的尾删

指定位置的尾删思路还是比较简单的,我这就给大家细细道来

思路:首先保证指定位置和指定位置的下一个节点不为空,为了便于大家可以清晰的分辨和理解,于是我定义了一个del指针让它代替pos->next,让pos->next = del->next,之后释放掉del并置为空。

链表的删除

 尾删:

思路:分两种情况讨论:

第一种:链表里只有一个节点时,直接释放掉*pphead,并且置为空即可,而判断它的条件:*pphead->next  ==  NULL;

第二种:连表里有多个节点时,先定义两个指针,使其中一个指针开始循环,另一个指针记录进行循环的指针的位置,当循环等指针的next指向空时,释放掉一开始循环的指针,并置为空,以及保存循环指针位置的指针的next也指向空

头删:

头删的思路比尾删的要简单许多,代码如下

保证链表和头节点不为空的情况下,先定义next指针,它负责接收*pphead的next指针指向的下一个节点,释放*pphead,最后将next赋给*pphead

链表的销毁

首先声明链表以及头节点的指针不为空,重新定义一个头节点指针prev,让prev进入循环,条件是prev不为空,进入循环后,重新定义一个指针next,它负责保存prev->next,然后释放掉prev, 再将next  的地址传给prev,跳出循环后将*pphead置为空,这样链表就销毁了。


当然这篇文章看下来,你可能还是会有些模糊,没事,我们不是还有总结环节嘛,下面就进入咱们的总结环节

总结:

1.    eg.prev->next   表示指针指向下一个节点,但指针还未移动

2.    eg.prev = prev->next   表示指针指向下一个节点,指针已经移动至下一个节点

3.    prev  =  pcur   表示pcur指针已经将它的地址和数值全传给了prev

4.    链表思路上的小妙招:去寻找插入以及删除节点时哪一个链条或哪几条链条被影响了,找到被影响的链条后,将其修改一下链接对象即可

5.关于pphead、 *pphead、**pphead还不清楚的同学可以参考一下下图


最后也祝大家在这个五一玩的开心

如果,你喜欢我的文章,不妨给我点个关注呗,如果有在这方面的问题也可以随时联系我哦

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

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

相关文章

Activiti7 开发快速入门【2024版】

记录开发最核心的部分,理论结合业务实操减少废话,从未接触工作流快速带入开发。假设你是后端的同学学过JAVA和流程图,则可以继续向后看,否则先把基础课程书准备好先翻翻。 为什么要工作流 比起直接使用状态字段,工作…

【 书生·浦语大模型实战营】作业(六):Lagent AgentLego 智能体应用搭建

【 书生浦语大模型实战营】作业(六):Lagent & AgentLego 智能体应用搭建 🎉AI学习星球推荐: GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方…

【机器学习】集成方法---Boosting之AdaBoost

一、Boosting的介绍 1.1 集成学习的概念 1.1.1集成学习的定义 集成学习是一种通过组合多个学习器来完成学习任务的机器学习方法。它通过将多个单一模型(也称为“基学习器”或“弱学习器”)的输出结果进行集成,以获得比单一模型更好的泛化性…

上海计算机学会2021年1月月赛C++丙组T2康托表

题目背景 康托是一名数学家,他证明了一个重要的定理,需要使用一张表: 这个表的规律是: 从上到下:每一行的分子依次增大;从左到右:每一列的分母依次增大。 康托以一种不重复、不遗漏的方式&am…

【深耕 Python】Quantum Computing 量子计算机(1)图像绘制基础

一、绘制静止图像 使用matplotlib库绘制函数图像y sin(pi * x): import math import matplotlib.pyplot as pltx_min -2.0 x_max 2.0N 1000x1 [] y1 []for i in range(N 1):x x_min (x_max - x_min) * i / Ny math.sin(math.pi * x)x1.append(x)y1.append(y)plt.xl…

关于继承~

继承 动物有猫、狗, 猫又分为加菲猫、布偶猫......;狗又有哈士奇、德国牧羊犬...... 我们发现,下一类除了拥有上一类的共性之外,还拥有自己的特性。 于是我们可以利用继承的方式来减少重复的代码 继承的基本语法 class A:p…

二叉树的直径

题目描述:给你一棵二叉树的根节点,返回该树的 直径 。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之间边数表示。 示例 1: 输入:root […

在剪映专业版中新增字体的方法

我一开始以为剪映专业版没有繁体字,结果发现有一个现代繁体,如图所示: 但是我已经下载了字体了,不用就可惜了。 点击汉仪粗黑繁,安装。 安装之后,重启电脑,打开剪映,就可以搜索到这个字体了。 这…

每日OJ题_贪心算法二④_力扣2418. 按身高排序

目录 力扣2418. 按身高排序 解析代码 力扣2418. 按身高排序 2418. 按身高排序 难度 简单 给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i,names[i] 和 heights[i] 表示第 i 个…

罗宾斯《管理学》第13版/教材讲解/考研真题视频课程/网课

本课程是罗宾斯《管理学》(第13版)精讲班,为了帮助参加研究生招生考试指定考研参考书目为罗宾斯《管理学》(第13版)的考生复习专业课,我们根据教材和名校考研真题的命题规律精心讲解教材章节内容。 序号名…

读天才与算法:人脑与AI的数学思维笔记17_歌曲的创作公式

1. 人为何创作音乐 1.1. 音乐一直具有算法性质,这意味着在所有的艺术形式中,它受到人工智能进步的威胁最大 1.1.1. 音乐也是所有艺术形式中最抽象的一种,它利用结构和模式,而正是这种抽象的性质使它与数学紧密相连 1.1.2. 在这…

查找算法之二分查找

一、算法介绍 二分查找,也称为折半查找,是一种在有序数组中查找特定元素的高效算法。对于包含 n 个元素的有序数组,二分查找的步骤如下: 确定搜索范围:首先,将要查找的元素与数组中间的元素进行比较。如果…

【C++】学习笔记——string_5

文章目录 六、string类7. string类的模拟实现8. string类的模拟实现的完整代码string.h头文件test.c源文件 9. string收尾写时拷贝 未完待续 六、string类 7. string类的模拟实现 我们之前讲了实现 insert ,但是那个插入函数仅仅是在 pos 位置插入一个字符而且&am…

13.1 QQ邮箱

1. 邮箱发送 2. 准备工作 3. 整合SpringBoot 3.1 配置 依赖引入 <!-- 邮件服务--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>application.…

发表博客之:transformer 架构 推理时候运算流程详细讲解,以及变长推理支持,小白都可以看得懂,AI推理工程师必备技能!

文章目录 [发表博客之&#xff1a;transformer 架构 推理时候运算流程详细讲解&#xff0c;以及变长推理支持&#xff0c;小白都可以看得懂&#xff0c;AI推理工程师必备技能&#xff01;](https://cyj666.blog.csdn.net/article/details/138439826)总结一下高性能变长推理 发表…

DevicData-P-XXXXXX勒索病毒有什么特点,如何恢复重要数据?

DevicData-P-XXXXXXXX这种新型勒索病毒有什么特点&#xff1f; DevicData-P-XXXXXXXX勒索病毒的特点主要包括以下几点&#xff1a; 文件加密&#xff1a;该病毒会搜索并加密用户计算机上的重要文件&#xff0c;如文档、图片、视频等&#xff0c;使其无法正常打开。这是通过强…

IoTDB 入门教程 问题篇②——RPC远程连接IoTDB服务器失败

文章目录 一、前文二、发现问题三、分析问题四、检查6667端口是否监听所有IP五、检查ECS云服务器的安全组是否允许六、检查Linux防火墙是否允许 一、前文 IoTDB入门教程——导读 二、发现问题 使用本地IP127.0.0.1可以连接IoTDB服务器使用远程IPxx.xx.xx.xx却连接不到。提示你…

抖音小店怎么运营操作,无货源正确做店方式,新手就看这一篇

大家好&#xff0c;我是电商笨笨熊 当前抖店还能做无货源模式吗&#xff1f; 当然可以。 近两年由于平台对于无货源的打击&#xff0c;很多人开始怀疑&#xff0c;无货源模式在抖店还能行得通吗&#xff1f; 抖店这个项目我们做了四年多的时间&#xff0c;无货源模式也是&a…

双fifo流水线操作——verilog练习与设计

文章目录 一、案例分析二、fifo_ctrl模块设计2.1 波形设计&#xff1a;2.2 代码实现2.2.1 fifo_ctrl2.2.2 顶层文件top_fifo_ctrl&#xff08;rx和tx模块省略&#xff09;2.2.3 仿真文件tb_fifo_ctrl 2.3波形仿真 一、案例分析 案例要求&#xff1a;写一个 fifo 控制器&#x…

vivado Aurora 8B/10B IP核(12)- Setp By Step搭建FPGA工程

Step1:任意创建一个新的空的工程&#xff08;创建工程的具体工程如果还不清楚的看我们教程第一季部分&#xff09;&#xff0c; 并且进入IP CORE列表 右击Customize ip Step2:配置 IP CORE-Core options Step3:配置 IP CORE-GT Selections Step4:配置 IP CORE-Shared Logic 为 …