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

news2024/12/24 8:09:33

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

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

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.coloradmin.cn/o/2257722.html

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

相关文章

如何高效的向AI大模型提问? - 提示工程Prompt Engineering

大模型的输入,决定了大模型的输出,所以一个符合要求的提问Prompt起到关键作用。 以下是关于提示工程Prompt Engineering主要方法的详细表格,包括每种方法的优点、缺点、应用场景以及具体示例: 主要方法优点缺点应用场景示例明确性…

python正则化表示总结

1.字符 总结: .匹配除“\n”以外的所有字符[…]字符集,…为所给出的范围,如:[a-zA-Z]表示逐个列出所有字符,[0-9]表示逐个列出所有数字[^…]^表示取反,如 [^0-9] 等同于出数字以外所有字符[…]并[…]也可…

BlueOS安装与DVL插件安装

我的blueos端又进不去了,查了查原因SD卡竟然裂开了!故重新下载附步骤: 官方网址:BlueOS Documentation DVL插件安装参考:Water Linked DVL A50 Support - Third Party Products / Sonar and Acoustics - Blue Roboti…

学者观察 | Web 3.0生态治理及其安全——北京交通大学副教授李超

导语 李超教授认为Web 3.0中无论是链上治理还是链下治理都有其优劣。链下治理机制更侧重于社区广泛参与和讨论,过程较为繁琐,但能够形成广泛的社区支持和参与,增强决策的合法性和接受度;链上治理机制通过直接在区块链上执行决策&…

C++实现排序算法:冒泡排序

目录 前言 冒泡排序性质 C代码实现冒泡排序 冒泡图解 第一趟排序 第二趟排序 第三趟排序 排序结果 结语 前言 冒泡排序的基本思想是通过从前往后&#xff08;从后往前&#xff09;两两比较&#xff0c;若为逆序&#xff08;即arr[i] < arr[i 1]&#xff09;则交换…

二叉树节点相关算法题|双分支节点个数|所有左叶子之和|每一层节点平均值(C)

双分支节点个数 假设二叉树采用二叉链表存储结构存储&#xff0c;试设计一个算法&#xff0c;计算一棵给定二叉树的所有双分支节点个数 算法思想 计算一棵二叉树中所有双分支节点个数的递归模型 若树为空&#xff0c;结果为0 若当前节点为双分支节点&#xff0c;递归左右孩子…

交互开发---测量工具(适用VTK或OpenGL开发的应用程序)

简介&#xff1a; 采用VTK开发应用程序时&#xff0c;经常需要开发各种各样的测量工具&#xff0c;如果沿用VTK的widgets的思路&#xff0c;绘制出来的的控件不够漂亮&#xff0c;且交互不太灵活&#xff0c;并且随着测量工具的增强&#xff0c;渲染的效率也会有所降低。基于上…

【LEAP模型建模】能源需求/供应预测、能源平衡表核算、空气污染物排放预测、碳排放预测、成本效益分析、交通运输碳排放、电力系统优化等专题应用

采用部门分析法建立的LEAP&#xff08;Long Range Energy Alternatives Planning System/ Low emission analysis platform&#xff0c;长期能源可替代规划模型&#xff09;是一种自下而上的能源-环境核算工具&#xff0c;由斯德哥尔摩环境研究所和美国波士顿大学联合研发。该模…

HarmonyOS-中级(三)

文章目录 合理使用动画和转场Web组件和WebView给应用添加通知和提醒 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;HarmonyOS专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月08日12点12分 合理使用动画和转场 动效场景设计&#x…

GC常见垃圾回收算法,JVM分代模型

如何判断是垃圾&#xff1f;引用计数器和Root可达性算法 如何进行清除&#xff1f;标记清除、复制、标记整理 堆分代模型&#xff1f;Eden&#xff0c;Surevivor&#xff0c;Tenuring 一个对象从创建到消亡的过程&#xff1f; 对象什么时候进入老年代&#xff1f; 一、GC&a…

win11 恢复任务栏copilot图标, 亲测有效

1、修改C:\Windows\System32\IntegratedServicesRegionPolicySet.json&#xff0c;解除中国不能使用copilot的限制。 使用Notepad搜索copilot全文搜索&#xff0c;将下面两处的“CN,”删除&#xff0c;删除后如下&#xff1a; {"$comment": "Show Copilot on t…

nginx生成自签名证书

nginx生成自签名证书 openssl genrsa -out server.key 2048 openssl req -new -subj "/CCN/STJiangSu/LSuZhou/Oldap/OUldap/CN10.20.24.101" -key server.key -out server.csr openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt …

【sgUploadImage】自定义组件:基于elementUI的el-upload封装的上传图片、相片组件,适用于上传缩略图、文章封面

sgUploadImage源码 <template><div :class"$options.name"><ul class"uploadImages"><liclass"uploadImage"v-loading"loadings[i]"v-for"(a, i) in uploadImages":key"i"click"click…

【重生之我在B站学MySQL】

MySQL笔记 文章目录 MySQL的三层结构SQL语句分类sql语句数据库操作创建数据库查看、删除数据库 表操作创建表mysql常用数据类型(列类型)查询表、插入值创建表练习创建一个员工表emp 修改表mysql约束primary key(主键)not null(非空)unique(唯一)foreign key(外键)check自增长 索…

Java版企业电子招标采购系统源业码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

eclipse启动的时候,之前一切很正常,但突然报Reason: Failed to determine a suitable driver class的解决

1、之前项目都是启动正常的&#xff0c;然后运行以后发现启动不了了&#xff0c;还会报错&#xff1a; 2、这个Reason: Failed to determine a suitable driver class&#xff0c;说是没有合适的驱动class spring:datasource:url: jdbc:sqlserver://192.168.1.101:1433;databa…

PostGIS分区表学习相关

在Postgresql中对空间数据进行表分区的实践_postgresql空间数据-CSDN博客文章浏览阅读1.4k次&#xff0c;点赞26次&#xff0c;收藏21次。Postgresql的分区功能允许将一个大表按照特定的规则拆分成多个小的分区表。这样做的好处在于&#xff0c;在查询数据时&#xff0c;可以只…

【sgUploadList】自定义组件:基于elementUI的el-upload封装的上传列表组件,适用于上传附件时

sgUploadList源码 <template><div :class"$options.name"><ul class"files"><li v-for"(a, i) in files" :key"i"><sgFileLink :data"a" remove"remove(a, i)" clearable /></…

C#核心(16)万物之父和装箱拆箱

前言 西方说人类的万物之父是亚当&#xff0c;中国说人类的万物之母是女娲&#xff0c;那么c#中有没有一个万物之父呢&#xff1f; 有&#xff0c;我们今天就来浅浅聊一下。 在C#和许多其他面向对象编程语言中&#xff0c;“万物之父”指的是Object类。这个类的历史和重要性…

网页核心页面设计(第7章)

一、生态家居网页 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthdevi…