数据结构(3)单链表的模拟实现

上一节我们进行了数据结构中的顺序表的模拟式现,今天我们来实现一下另外一个数据结构:单链表。

我们在实现顺序表之后一定会引发一些问题和思考:

1.顺序表在头部和中间插入数据会用到循环,时间复杂O(N)

2.顺序表增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗

3.顺序表增容一般是成二倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了之后增     容到200,再继续插入五个数据,后面没有数据插入了,那么就浪费了95个数据空间。

每一种数据结构在实际应用中都有自己的优势和劣势

思考:如何解决上述问题呢?

我们引入另外一种数据结构:单链表。

一.单链表的结构和概念

概念:逻辑结构:连续       物理结构:非连续。

结构:

1.结点

与顺序表不同的是,链表里的每个数据都是存储在独立申请下来的空间中(结点)的。

结点主要由两部分组成:当前结点要保存的数据和保存下一个结点的地址(指针变量)

图中指针变量plist保存的是第一个结点的地址,我们称plist此时指向第一个结点,如果我们希望plist指向第二个结点时,只需要修改plist保存的内容为0x0012FFA0.

链表中的每个结点都是独立申请的(即需要插入数据时才去申请一块结点的空间),我们需要通过指针变量来保存下一个结点位置才能从当前结点找到下一个结点。(构建每个结点之间的联系)

2.链表的性质

1.链表在逻辑结构(想象)上是连续的,在物理结构(实际)上不一定连续。

2.结点的申请一般使用malloc函数,实在堆空间上申请的。

3.从堆上申请来的空间,是按照一定策略分配出来的,每次申请的空间可能连续,也可能不连续。

结合C语言阶段的知识,我们可以给出每个结点对应的结构体代码:

假设当前保留的结点中的数据为整型:

struct SListNode
{int data;//结点数据struct SListNode* next;//指针变量用于保存下一个结点的地址
};

当我们想要保存一个整型数据的时候,实际上是向操作系统malloc申请了一块内存,这个内存不仅要保存整型数据,也需要保存下一个结点的地址(当下一个结点为空时保存的地址为空)。

当我们想要从第一个结点走到最后一个结点时,只需要在当前结点拿到下一个结点的地址就可以了。

二:模拟实现单链表

0.定义链表的结构

链表的核心是结点,定义链表的结构就是定义结点的结构。

至于之所以要将int进行typedef重命名,参考上一篇博客————顺序表。

1.链表内容的打印

打印链表内容之前,先来构建一个链表。

这一步的思路是将链表的首结点(火车头)作为函数参数传给函数,接着遍历链表依次打印,直到打印完所有结点数据为止。

2.创建一个新结点

3.尾插

(单链表的尾部插入结点)

在插入结点之前首先你要创建一个结点,在判断链表是否为空,如果为空,插入到第一个位置(直接赋给*pphead)就可以了。如果此时单链表已有结点,就循环找到单链表的最后一个结点,在将申请带来的新结点插入到尾部(构建尾结点和新结点的关系)

这里需要注意:

1.函数传参时一定传的是phead的地址,用二级指针接收,否则无法构建新的指向关系(传值调用VS传址调用)(传值的话形参是实参的临时拷贝,出了函数作用域后形参销毁,构建不起实参和新结点的指向关系)(只能构建起形参与新结点的指向关系)。

2.遍历链表时尽量创建一个新的指针去遍历,而不是使用*pphead去遍历,让*pphead始终指向首结点,否则就不容易再次找到头节点了。

4.头插

在单链表的头部插入数据(将申请来的新结点作为单链表的首结点)

头插的话就不用考虑链表内容是否为空了,因为即使链表内容为空,*pphead==NULL,上面程序的逻辑也能解决问题。

单链表头插结点的时间复杂度为O(1).

5.尾删

删除单链表的尾结点

与头删不同的是:

1.尾删首先是要有结点可删,assert还要断言一下*pphead.

2.如果单链表中只有一个结点,直接释放就可以了。如果单链表中不仅仅有一个结点,不能直接释放。因为如果直接free(ptail->next);的话,尾结点就彻底找不到了,应该先保存尾结点的位置。

6.头删

删除单链表的头结点(首结点)

删除头结点不能之间将*pphead释放,否则后面的结点就找不到了。

因该先保存一下第二个结点,再去释放第一个结点。最后改变*pphead的指向。

注意:请看上图的89行,结构体和指针这两部分操作符的优先级问题比较复杂,在写程序时尽量加上括号,以防出现问题。

7.查找

与前面单链表不同的是,单链表中查找数据这一操作只是涉及到查找,不会涉及到改变phead的指向,因此采用传值调用即可。

如果找到了会返回指向带有x数据结点的指针,要是没找到,返回空指针。

查找这一操作经常与后续指定位置的操作结合使用。

8.在指定位置之后插入数据

凡是涉及到插入结点的操作,都要先创建一个新结点。

注意:在指定位置之后插入数据这一操作中上图116行和117行的操作不能交换顺序。

9.在指定位置之前插入数据

注意:

在指定位置之前插入数据首先要找到指定位置的前一个结点,再构建该结点和指定位置结点与新结点之间的关系。

这个操作要先检查一下是否pos就是头结点,如果是的话直接调用头插。

本操作137行和138行的内容是可以互换的。

10.删除pos位置的结点

要想删除pos位置的结点,要先找到pos位置前一个结点,构建完pos位置前一个结点和pos位置后面的一个结点的位置关系之后,再去释放pos位置的结点。

11.删除pos位置之后的一个结点

和10一样,删除结点(free释放结点动态申请的内存)之前要先构建pos位置结点和pos之后数两个位置的结点(要删除的结点的后面一个结点)之间的关系。

12.销毁链表

当链表使用完毕之后一定不要忘记将链表结点申请在堆空间上的动态内存回收

注意:

1.回收的方式是从前向后(因为从后向前的话不好弄,本节讨论的是单链表,是不能从后往前访问的)

2.不能直接释放首结点(否则后面就找不到了)。

3.释放每个结点之前都要保存一下下一个结点,否则就找不到了(释放不完全,没释放的也找不到了)。

三:单链表总结

相较于顺序表

单链表在中间或者头部插入或者删除数据时间复杂度为O(1),而顺序表为O(n).

单链表在尾部插入或者删除数据时间复杂度为O(n),而顺序表为O(1)。

不同的数据结构都有各自独特的优势(当然也有劣势)

没有哪个好哪个坏这一说法

看实际应用的场景,不同的场景要使用不同的数据结构!

完:

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

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

相关文章

uni-app 组成和跨端原理 【跨端开发系列】

🔗 uniapp 跨端开发系列文章:🎀🎀🎀 uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…

操作系统:中断与处理器调度

目录 1、中断与中断系统 中断概念: 中断装置: 中断相关概念: 中断优先级别与中断屏蔽 2、处理机(CPU)调度 调度相关参数:P62 调度算法: 处理机调度时机 处理机调度过程 3、调度级别与多…

两种距离度量简记

一、Lp距离/Minkowski 距离(Minkowski distance) 1、Lp距离: 特征空间中两个实例点的距离是两个实例点相似程度的反映。Lp距离是一种一般化的距离度量 设特征空间x是n维实数向量空间Rn xi,xj的Lp距离定义为(p>1&…

从零开始的使用SpringBoot和WebSocket打造实时共享文档应用

在现代应用中,实时协作已经成为了非常重要的功能,尤其是在文档编辑、聊天系统和在线编程等场景中。通过实时共享文档,多个用户可以同时对同一份文档进行编辑,并能看到其他人的编辑内容。这种功能广泛应用于 Google Docs、Notion 等…

centos7 离线安装7z

1、下载7-Zip 下载地址:7-Zip - 程序下载 2、解压 mkdir 7zip --创建文件夹7zip mv 7z2301-linux-x64.tar.xz 7zip/ --移动 cd 7zip tar -xvJf 7z2301-linux-x64.tar.xz --解压 输入ll 查看解压后的文件 3、安装cp 7zzs /usr/local/bin/ 输入7zzs 查看是否安装成功…

顶会新宠!KAN-LSTM完美融合新方案

2024深度学习发论文&模型涨点之——KANLSTM KAN-LSTM混合预测模型是一种结合了自注意力机制(KAN, Key-attention network)和长短时记忆网络(LSTM)的深度学习模型,主要用于序列数据的预测任务,如时间序…

CondaError: Run ‘conda init‘ before ‘conda activate‘

rootautodl-container-543e4aa3a7-e596c47a:~# conda activate python37 CondaError: Run ‘conda init’ before ‘conda activate’ conda 激活虚拟环境的时候报错,提示需要进行初始化,但是初始化之后仍然不生效。 1、初始化 conda init2、重新加载环…

Java_实例变量和局部变量及this关键字详解

最近得看看Java,想学一学Flink实时的东西了,当然Scala语法也有这样的规定,简单看一下这两个吧,都比较容易忽视 实例变量和局部变量 实例变量和局部变量是常见的两种变量类型,区别 作用域: 实例变量:实例变…

代理模式的理解和实践

代理模式(Proxy Pattern)是一种结构型设计模式,它允许你为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理对象间接地访问目标对象。通过这种方式,代理模式…

Autoformer: 一种基于自动相关机制的时序预测新架构

论文题目: Autoformer:Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting 论文地址:https://openreview.net/pdf?idI55UqU-M11y 今天给大家介绍一篇时序预测领域的重要算法——Autoformer,由李华等人于2020年提出&am…

2024-12月js逆向案例-sensor-data之vmp字段之akamai_2/3.0-(下)

目录 一、初始插桩二、长串的由来三、短串的由来2024-12月akamai_2.0-sensor-data之cookie反爬分析详细教程(上)2024-12月akamai_2.0-sensor-data之cookie反爬分析详细教程(中)一、初始插桩 1、其实就是研究dFT的由来,解混淆得到如下**var dFT = ‘’‘concat’‘concat’…

GAMES101:现代计算机图形学-笔记-10

今天来聊一些基本的概念:相机,棱镜与光场。 众所周知,成像的方法有两种:合成与捕获。 像我们之前所学的内容如光栅化,如光线追踪,本质上都是合成图像的方法,他们只是在计算机中模拟来成像。 那…

深信服ATRUST与锐捷交换机端口链路聚合的配置

深信服ATRUST业务口原来只配置使用一个电口,近期出现流量达到800-900M接近端口的极限带宽。由于设备没有万光口,于是只好用2个光口来配置链接聚合。 下需附上深信服ATRST端口配置的截图,由于深信服ATRUST与锐捷交换机端口只共同支持源mac目的…

华为HarmonyOS NEXT 原生应用开发:页面路由、页面和组件生命周期函数

页面路由、组件生命周期 一、路由的基本使用 1. 如何新建页面 直接右键新建Page。【这个是最直接最常用的】新建普通ets文件,然后通过配置变成页面。 【该方法是遇到这种情况的解决方案】 2. 路由 - 页面之间的跳转 使用 **router.pushUrl({}&#xff…

Vulhub:Log4j[漏洞复现]

CVE-2017-5645(Log4j反序列化) 启动靶场环境 docker-compose up -d 靶机IPV4地址 ifconfig | grep eth0 -A 5 ┌──(root㉿kali)-[/home/kali/Desktop/temp] └─# ifconfig | grep eth0 -A 5 eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 in…

电子商务人工智能指南 4/6 - 内容理解

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

`yarn list --pattern element-ui` 是一个 Yarn 命令,用于列出项目中符合指定模式(`element-ui`)的依赖包信息

文章目录 命令解析&#xff1a;功能说明&#xff1a;示例输出&#xff1a;使用场景&#xff1a; yarn list --pattern element-ui 是一个 Yarn 命令&#xff0c;用于列出项目中符合指定模式&#xff08; element-ui&#xff09;的依赖包信息。 命令解析&#xff1a; yarn list…

播放器秒开优化

开篇 先说结论&#xff1a; 字节跳动就曾给出过一份数据&#xff1a;对一部分型号的 Android 手机&#xff0c;播放首帧时长从平均 170ms 优化到 100ms&#xff0c;带来了 0.6% 左右的用户播放时长提升。 衡量指标&#xff1a; 播放秒开率&#xff0c;指的是播放器开始初始…

docker nginx 部署vue 实例

1.安装docker https://blog.csdn.net/apgk1/article/details/144354588 2. 安装nginx docker 安装 nginx-CSDN博客 3. 复制 nginx-test 实例的一些文件到宿主机中&#xff0c;目前已 /home/jznh/路径演示 3.1 在/home/jznh/ 创建 conf html logs 三个文件夹&#xff0c;…

技术人员需要成为的八边形战士

那天偶然看到一个标题&#xff1a;脾气好&#xff0c;技术佳&#xff0c;哪个程序员这么宝藏&#xff1f;我没有点进去看内容&#xff0c;但是心里在琢磨一件事&#xff1a;10年前这种宝藏程序员很难得&#xff0c;现在的市场&#xff0c;恐怕不够。恐怕市场在找的都是下面技能…