单链表(配图详解每一个函数接口)(上)

简介: 单链表(配图详解每一个函数接口)(上)

前言:Hello!大家好,我是@每天都要敲代码,上一期给大家带来了线性表之===》顺序表,没有学会的小伙伴可以再去学习一下吧!传送门 接下来我们先分析一下顺序表:


顺序表问题:

问题1:中间/头部的插入删除,都要进行数据的移动,时间复杂度为O(N)。

问题2:增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。

问题3:增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:

如何解决以上这种问题呢?下面给出了链表的概念和结构来看看。


概念和结构:


概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。


结构:

b7248f1c76654e809f6f9e8855aa3b16.png


种类

实际中要实现的链表的结构非常多样,以下情况组合起来就有gif.gif=8种链表结构:

1. 单向、双向

2. 带头、不带头

3. 循环、非循环


cadac91b463d47ef9011e70ab509c48b.png

37137a3915b740d4b533da3d879c36f8.png


4bf70b42577345fda2b79c7855cf571e.png


虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:


82e16e31676e4bf2bf67da9ed25bf445.png


无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结

构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都

是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带

来很多优势,实现反而简单了。


有了前面这些概念和结构,相信大家对链表已经有了初步的理解和印象,接下来让我们来一起学习无头单向非循环链表:


无头单向非循环链表:


1.创建单链表:SListNode


单链表创建的结构和顺序表是很相似的,这里我们只需要两个参数,一个data用来存储数据;一个next指针,用来指向下一个地址;并且我们用的是无头单向非循环链表,所以我们才开始的头指针plist初始化为NULL!那如果是带头结点的单链表呢?此时的plist就需要初始化成为一个malloc开辟的地址,这个等我们下一期讲到带头双向循环链表就会用到,这里就不在赘述。


ab440c68902f4c37907791b01f4d74fd.png


2.尾插函数的实现:SListNodePushBack

动态开辟空间的函数:SListNodeCreat


在这里的无论是插入还是删除,我们都可以去画图理解,这样也能防止写错。我们每次的插入都需要malloc动态开辟一个空间,所以不妨直接封装成一个函数SListNodeCreat,便于后面的使用,并且我们在开辟空间时,如果能开辟成功了,就把newnode给赋值上:newnode->data = x  newnode->next = NULL,下面看动态开辟空间的函数实现。


具体代码如下:



129f3b14f4414d6f983ce079b7e68ac1.png


动态开辟空间成功后,我们就开始尾插,这时就需要我们画图去理解了:


情况1:链表里本身就有很多数据,我们这时只需要找到尾结点(暂定为tail),把tail->next=NULL改成tail->next = newnode就可以,至于newnode->next=NULL就不需要写了,因为我们开辟空间时就已经让newnode->data=x和newnode->next=NULL了,下面看具体逻辑图:


97ea760bc5704a1c9d009267f1df861e.png


情况2:像我们现在刚开始使用的的一样,才开始就是一个空链表,我们第一次就进行了尾插,此时的*pphead和tail肯定都为空指针,这时我们只需要把才开辟的空间newnode赋值给*pphead就可以了,具体逻辑图:

1392ab861566421da6738bf35e697352.png


所以尾插时我们要考虑这两种情况,具体代码如下:


88bb58f27aee4f2fbc4e2edf2f1c067b.png

尾插几个数据我们先打印验证一下,具体打印函数下面就会给出:


721b795814a24b199205f51899b3a2e3.png

3.打印函数的实现:SListNodePrint

打印函数也很简单,这里就不在多说,直接给出代码:


152e5cb351694f9bb1e37be8404e24eb.png


4.头插函数的实现:SListNodePushFront


   对于头插函数就很简单了,它不像顺序表那样还需要移动后面的元素,所以无论是空链表还是有元素的链表都是一样的;这里通过指针直接链接,下面看具体逻辑图:


55e34ff381604a7485c7e09fb3782ec7.png

下面看具体代码:

6e09be20461947bb8965d67a1e5861ed.png

我们不妨头插一个0,进行打印验证:

993558326943423288e5162dcaf28056.png

之后我们也可以屏蔽掉前面尾插的函数,直接对空表进行头插,进行验证:


6ff597d33cf14b468e0d42e0f2b8a019.png


5.尾删函数的实现:SListNodePopBack


   对于尾删函数的实现可能就比较麻烦了,我们还是需要分情况讨论,先从最普通的情况进行画图分析,然后在把哪些特殊的情况单独拿出来分析:


情况1:链表里本身有很多元素,我们进行尾删时怎么办呢?肯定需要找到尾指针tail,因为我们malloc动态创建的,最后不使用了肯定要free释放掉;那还需要知道什么呢?我们还需要把最后一个指针的next置为空啊!我们都已经释放掉尾指针tail怎么找它前面一个指针prev把它的next置位空呢?所以我们还需要一个指针prev记住tail的前一个指针,下面看逻辑图:


6ec6cd32e54848b7b65af14513d83b50.png


情况2:如果是空链表呢?我们直接return退出不就好了,就不需要我们去删除了!

情况3:如果只有1个节点呢?尾结点就是头结点,尾结点tail前面根本没有一个节点prev怎么办呢?我们就直接释放掉当前的节点,然后置空就可以了:


dad7e7d9efc847f88972aba453e07e92.png

下面看具体代码:


378bd5cfb6e54822b40f6a5dd5f39284.png

不妨尾删一个数据测试结果:


a2f06328a9264ae3ac3ce164a58f3b5e.png

相关文章
|
搜索推荐 Java 开发者
从 Java 小白到大神:一文带你搞懂子类如何“继承”父类江山,开创新世界!
【6月更文挑战第16天】Java中的继承是面向对象的核心,它允许子类继承父类的属性和方法,提高代码复用。通过实例,如`Animal`和`Dog`类,显示了如何创建和覆盖方法。继承不仅简化代码,还支持多态性,是构建可扩展系统的关键。从新手到专家,掌握继承意味着掌握编程的强大工具,能解锁更复杂的系统设计和优化。
300 3
|
网络协议 安全 Java
分布式(基础)-RMI的原理
分布式(基础)-RMI的原理
用直播带货的选品思维做理财服务, 支付宝“金选”有戏吗?
用直播带货的选品思维做理财服务, 支付宝“金选”有戏吗?
233 0
用直播带货的选品思维做理财服务, 支付宝“金选”有戏吗?
|
Oracle 关系型数据库 数据库
圣诞快乐 | 盘点2017最受欢迎的原创文章
Elon Musk圣诞节信的2017版本。 马斯克在信中称自己是“外星人”,自己与时间的关系跟“地球人”不一样。他在信中分享了他的家人——五个孩子的最新成就:包括 SpaceX(15岁)、Tesla(14岁)、OpenAI和Neuralink(2岁,1岁)、Boring Company(1岁)。
5053 0
|
新零售 关系型数据库 MySQL
【招聘】杭州有赞招聘 MySQL DBA
写在前面     曾经给其他朋友 公司写了很多招聘广告,现在终于要为自己写一篇来招聘DBA了。本人花名 杨一 ,真名就是博客上面的名字啦 ,从毕业一直做DBA,在阿里工作四年半,经历阿里云,RDS DBA,外部去IOE项目组,阿里集团电商业务DBA,现在就职于杭州有赞科技有限公司.    有赞 ,是一家零售服务技术提供商,为商家提供全套移动电商产品服务方案。
1697 0
|
C++
RvmTranslator4.1 in PDMS
RvmTranslator4.1 in PDMS eryar@163.com In order to export PDMS model to other system more convenient, I wrapped the RvmTranslator in PDMS by PML.
1357 0
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!