• 单链表思路讲解+C语言代码实现


    学海无涯,苦作舟啊!
    老铁们加油
    源代码放在总结处,需要的同志可以直接跳转到最后

    什么是单链表

    在学习完顺序表之后,我们就来学习一种新的数据结构–单链表,关于链表,其实有很多种,单链表,双链表,循环链表 …等等。

    在学习完顺序表之后,我们仔细比对它与数组之间的区别,其实并不是很大,所以在实现顺序表的时候,相对的容易很多,但是上一篇文章的结尾我们也说了,顺序表在内存中是连续存储的,不仅仅很容易造成空间碎片,而且有时在插入的时候,需要移动大量的元素,这无疑造成了效率降低。

    那么此时,计算机的前辈们就想,能不能把内存中那些零散的空间利用起来,这时,我们的链表就来了。

    回想一下我们在实现顺序表的时候,是通过“下标(size)”来找到要存储和删除元素的,那我们在链表中也是用一个类似下标(其实就是指针,后面解释)的东西来记录下一个元素的地址,这样就不必需要各个元素是连续的了,我们通过指针就可以找到下一个元素的位置,进行访问了。
    示意图:
    在这里插入图片描述
    (注意这里我画的箭头都是单向的,后面讲到双向链表的时候,会对其修改,我们先从最简单的单链表开始)

    单链表的结构图讲解

    所以我们现在了解到,单链表需要一个data的数据域和一个指针域,最后一个指针域的指针指向NULL,表示链表的结束。一个数据域和指针域组成的结构称为结点
    在这里插入图片描述

    那么遍历一遍链表,即可知道链表的长度。
    通过修改指针的指向即可完成插入和删除(后面在实现各种函数的时候,会讲解),时间复杂度为O(1)!是不是比顺序表的O(n)好多了。

    单链表对内存空间的要求很低,即使你的链表很长,链表也能创建成功,那么就有人问了,难道链表不会创建失败吗?

    当然不是,但是想象一下,当我们的链表创建失败是什么场景,内存中一点零散的空间都没有了!!这是很危险的,这时候的电脑很容易造成崩溃,还谈什么链表呢。

    **说到这,相比大家也就明白了一点,和顺序表不同的是,链表是不需要静态这种结构的,链表的结点时按需创建的,也就是你用多少我就给你多少。**这也是相比于顺序表的优势之处。

    创建链表

    好了,了解完链表的基础结构之后,我们就来手撕单链表把!
    前面说到需要数据域和指针域两个变量,所以我们还是使用结构体来创建一个结点(这一点在后面的数据结构的讲解中就不再说了)。
    在这里插入图片描述
    首先假设创建了一个长度为5的单链表,那此时就需要有一个函数(数据结构种这种函数也成为接口),来实现创建单链表的操作。

    单链表的创建分为两步
    1.生成结点
    2.将结点链接起来(串联起来)

    所以我们封装两个函数,一个负责实现生成(BuySLnode),一个负责实现链接(CreatetSL)
    在这里插入图片描述
    在这里插入图片描述
    因为考虑到后面的插入时,还需要BuySLnode函数来生成结点,所以我们将创建链表封装成两个函数,以此来减少代码量。

    打印链表

    打印链表的实现没什么好讲的,只需要遍历链表,当结点的指针域为NULL 时就停止遍历即可。
    在这里插入图片描述

    OK,我们现在来测试一下这两个函数是否能达到我们的预期
    运行截图:
    在这里插入图片描述

    OK那么我们接着往下走

    尾插链表

    接下来要实现的是尾插链表,这个函数的实现我们会解释的相对清晰一点,因为很多初学者不明白这个要使用二级指针。之后的函数讲解会相对的快一些。

    想来讲解一下思路,要想在链表的尾部插入一个新的结点,首先我们要先遍历整个链表,找到表尾,之后将表尾的指针域指向新结点的地址,然后将新结点的指针域指向NULL
    在这里插入图片描述
    思路很简单,但是我们要想明白一件事,就是我们要对原来的链表进行修改,那这时候我们就要传原来链表的地址过去,而不能将原来链表的地址作为值进行传参(因为我这里实现的函数都是void类型的,所以要使用二级指针进行传参),这样链表才能被修改。
    在这里插入图片描述
    然后在插入时,我们同样需要思考一件事情,如果当前链表为空的话该怎么进行插入,这时就有同志说,简单啊!按照上面的方式直接插入不就行了吗。

    天真了!老铁

    错误代码:
    在这里插入图片描述
    如果链表为空的时候,我们还这样写,那么就是对空指针的使用了!
    正确的做法应该是在前面加上判断是否为空链表的判断
    正确代码:
    在这里插入图片描述
    这才是完整的尾插,大家结合我的注释应该能看的懂这一过程,如果对你来说有点吃力,那建议反复查看,特别是为什么使用二级指针这一部分,后面的函数的讲解就会加快一些节奏了。

    尾删链表

    大家先看一下代码,然后我来解释,有疑惑没关系,接着往下看就得了。
    在这里插入图片描述
    首先删除的链表肯定不能为空,所以进行断言一下,保证代码的安全性。
    然后我们先来看正常的删除的情况
    在这里插入图片描述

    第一步先找到倒数第二个结点的位置
    然后将该结点指向NULL
    释放最后的结点

    但是如果链表的长度为1呢?
    这时根本不存在倒数第二个结点,这时就要在前面加一个判断的条件了,如果当前链表的长度为1的话,就直接释放结点,并将头指针(指向第一个结点的指针称为头指针)改为NULL。

    对于链表长度为1的情况,还是有一种解决的办法,用另外一个指针来记录cur的前一个结点的地址,这时候只需要对前一个结点进行修改即可,不需要再进行链表长度的判断了。
    在这里插入图片描述

    头插链表和头删链表

    因为头插链表和头删链表的操作相对的来收,算是比较简单的,所以我们放在一起来讲,首先我们还是先来了解一下思路。

    我们先来看头插的实现思路。
    要想在链表的第一个结点位置插入一个新的结点,那么这个新的结点将取代旧的结点,那么就需要将新结点的next指向原来的结点,然后再改变结点的地址,见下图:
    在这里插入图片描述
    代码:
    在这里插入图片描述
    因为条件的原因,后半部分的代码都以这种图片给出,但是源代码还是不变,链接放在最后了。

    接下来我们再来看一下头删的实现。
    其实也很简单,只需要将头结点赋值给第二个结点,然后释放掉第一个结点就好了,然后用assert断言一下空表的情况。
    在这里插入图片描述

    查询链表

    这里我们实现的查询链表的功能是,如果找到了这个结点,那么就把这个结点的地址返回,如果查找失败的话就返回NULL。
    思路也很简单,遍历链表即可,没什么难度。
    在这里插入图片描述
    同样的,大家要注意点空表的情况。

    特定位置插入

    接下来的两个功能的实现,稍微有一丢丢的复杂,但是肯定还是能理解的。
    这里我们在特定位置的后面进行插入新结点,之所以不在前面的是因为,如果想要在特定位置的前面进行插入,就需要先遍历整个链表找到前一个结点的位置,是比较浪费时间的。

    功能要求是,输入一个结点,然后在这个结点之后的位置进行插入新的结点。
    需要考虑的意外情况就是,输入的结点不能为空,所以我们需要断言一下。

    先用一个指针cur记录下pos之后的那个结点的位置,然后插入新结点,然后让新结点指向cur。
    在这里插入图片描述

    在这里插入图片描述
    同样的顺序不能乱!!

    特定位置删除

    特定位置的删除也比较容易,只需要将该位置的前一个的结点指向该位置的下一个结点,然后再释放掉该结点就OK了。
    在这里插入图片描述
    当我们要删除的结点是第一个结点时,上面所说的思路就不行了,因为第一个结点前面并没有其他的结点了,这时候我们只需要调用头删的函数就好了,尾结点的删出,上面的方法依然有效,所以只需要看情况条用头删即可。
    在这里插入图片描述

    销毁链表

    最后便是销毁链表,依次释放所有的结点,然后指针指向空即可。
    在这里插入图片描述

    总结

    先给出源代码的地址链接:代码地址

    我们来回归一下从一开始的创建单链表和各个功能函数的实现,其实无非就是通过控制next指针来完成主要的插入和删除,其中有些功能的实现的顺序并不能乱,当大家自己写一遍单链表之后,也就能记住了,关键是如何从无到有的这个思路是怎么来的,如果大家对上面的思路和代码有自己的见解和优化的话,之后一定要尝试修改一下。
    单链表只是链表结构中最简单的一种结构,只有真正的掌握了单链表的实现,才能继续向下开展新的学习!

  • 相关阅读:
    4.Docker 搭建 redis6
    React报错之Parameter 'event' implicitly has an 'any' type
    vue中使用图像编辑器tui-image-editor(一)
    springboo幼儿园书刊信息管理系统毕业设计源码141858
    数据结构与算法分析——数学基础(为之后的算法分析打基础)
    CMSC5707-高级人工智能之自编码器Auto-encoders
    项目实战:通过axios加载水果库存系统的首页数据
    机器学习笔记 - 3D 对象跟踪极简概述
    七大排序之希尔排序
    jsp+ssm二手车交易管理系统 毕业设计-附源码151159
  • 原文地址:https://blog.csdn.net/Javaxaiobai/article/details/127622563