数据结构之链表深度讲解

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

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


链表结构体内的元素

和顺序表里一样创建一个自定义类型的结构体,并且创建一个自定义类型的变量,以及指向下一个节点的指针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还不清楚的同学可以参考一下下图


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

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

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

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

相关文章

JavaScript 动态网页实例 —— 文字移动

前言 介绍文字使用的特殊效果。本章介绍文字的移动效果,主要包括:文字的垂直滚动、文字的渐隐渐显、文字的闪烁显示、文字的随意拖动、文字的坠落显示、页面内飘动的文字、漫天飞舞的文字、文字的下落效果。对于这些效果,读者只需稍加修改,就可以应用在自己的页面设计中。 …

4.3 JavaScript变量

4.3.1 变量的声明 JavaScript是一种弱类型的脚本语言,无论是数字、文本还是其他内容,统一使用关键词var加上变量名称进行声明,其中关键词var来源于英文单词variable(变量)的前三个字母。 可以在声明变量的同时对其指定…

多线程与信号量简介

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

你知道什么是防抖和节流吗?

目录 1 先举个例子 2 使用场景 3 代码实现 3.1 防抖的实现 3.2 节流的实现 1 先举个例子 防抖,更像是坐电梯,早上眼看9点了,都着急坐电梯上去打卡,但眼看电梯要关了,进来一个人,等几秒,…

uniapp乡村社区户籍问外来人员管理系统 微信小程序python+java+node.js+php

基于微信小程序的外来人员管理系统项目的概述设计分析,主要内容有的私教预约平台系统平台的具体分析,进行数据库的是设计,数据采用MySQL数据库,并且对于系统的设计采用比较人性化的操作设计,对于系统出现的错误信息可以…

信创 | 信创产业人才需求与培养机制:优化策略与实践探索

信创产业的人才需求与培养机制面临着多方面的挑战和机遇。首先,信创产业的快速发展带来了巨大的人才需求,但目前人才培养供给与企业发展需求之间存在不匹配的问题。这种不匹配主要表现在课程体系不健全、产教融合不够深入、校企联动性不足以及职业培训市…

探索动态内存开辟的奥秘

✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论 个人主页:秋邱博客 所属栏目:C语言 前言 开始之前,我们先来了解一下C/C中程序内存区域划分。 在C/C程序中,内存区域通常被划分为以下几个部分: 1.栈&…

第16章 基于结构的测试技术(白盒测试技术)

一、静态测试技术 (一)概述 不运行程序代码的情况下,通过质量准则或其他准则对测试项目进行检查的测试类型,人工或工具检查。 1、代码检查 2、编码规则检查 3、静态分析 静态分析概述 不需要执行程序 控制流分析 通过生成…

短视频矩阵系统源码==3年源头开发

一 短视频矩阵系统具备以下特点: 1.内容管理功能:用户可以在系统中多账号托管 一次性上传、编辑和发布多个短视频平台的内容,无需在每个平台上重复操作,从而提高工作效率并保持内容的一致性和高质量 2.批量剪辑视频:系统支持上传批量素材管理剪辑 视频…

Visual studio调试技巧

Visual studio调试技巧 bug是什么?Debug和ReleaseDebugRelease 如何调试VS调试快捷键调试过程中查看程序信息查看临时变量的值查看内存信息查看调用堆栈查看汇编信息查看寄存器信息 编译常见错误编译型错误链接型错误运行时错误 bug是什么? bug的英文释…

SAM:Segment Anything Model

论文(ICCV,fackbook):Segment Anything 源码: https://github.com/facebookresearch/segment-anything demo:Segment Anything | Meta AI (segment-anything.com) 一、摘要 本文介绍了“Segment Anything…

活动回顾 | 春起潮涌——硬件驱动的量化交易与AI

4月20日,华锐技术ACLUB联合AMD在上海举办了“春起潮涌——硬件驱动的量化交易与AI”沙龙活动,会议围绕FPGA硬件加速、CPU&网卡调优、AI技术应用等展开,近50位量化IT与分享嘉宾一起探讨硬件技术在量化交易和AI领域的应用和创新。 FPGA在交…

【C++第七课-string用法】

这里写自定义目录标题 string的初步介绍sring的构造函数string的构造函数-重点掌握无参的构造函数用常量字符串来初始化拷贝构造 string的构造函数-非重点掌握拷贝字符串str从pos位置开始的len个字符拷贝字符串s的前n个字符用n个c去初始化 string的赋值string的遍历和访问下标[…

爬虫自动化之drissionpage实现随时切换代理ip

目录 一、视频二、dp首次启动设置代理三、dp利用插件随时切换代理一、视频 视频直接点击学习SwitchyOmega插件使用其它二、dp首次启动设置代理 from DrissionPage import ChromiumPage, ChromiumOptions from loguru

matplotlib/seaborn 绘图可视化全面总结

1.概述 使用Matplotlib 绘图实现可视化时,会面临不同的需求有所调整,本文档重点对绘图过程中产生的一些小众需求进行全面总结,其他任务时可以随时即抽即用。 2.绘图 2.1 一般绘图 plt.figure() 参数设置说明 matplotlib.pyplot.figure( …

C++设计模式-创建型设计模式

设计模式 设计模式是什么 设计模式是指在软件开发中,经过验证的,用于解决在特定环境下,重复出现的,特定问题的解决方案;其实就是解决问题的固定套路。但是要慎用设计模式,有一定的工程代码量之后用它比较…

【论文阅读】Tutorial on Diffusion Models for Imaging and Vision

1.The Basics: Variational Auto-Encoder 1.1 VAE Setting 自动编码器有一个输入变量x和一个潜在变量z Example. 获得图像的潜在表现并不是一件陌生的事情。回到jpeg压缩,使用离散余弦变换(dct)基φn对图像的底层图像/块进行编码。如果你给…

先电2.4的openstack搭建

先电2.4版本的openstack,前期虚拟机部署参考上一篇2.2版本,基本步骤是一样的,准备两个镜像文件CentOS-7.5-x86_64-DVD-1804.iso,XianDian-IaaS-V2.4.iso [rootcontroller ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno16777…

华为OD机试 - 小扇和小船的数字游戏 - 二进制(Java 2024 C卷 200分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试…

论文笔记(四十五)Attention Is All You Need

Attention Is All You Need 文章概括摘要1. 介绍2. 背景3. 模型架构3.1 编码器和解码器堆栈3.2 Attention3.2.1 按比例点积Attention3.2.2 Multi-Head Attention3.2.3 注意力在模型中的应用 3.3 定位前馈网络3.4 嵌入与 Softmax3.5 位置编码 4 为什么 Self-Attention5. Trainin…