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

news2025/2/21 4:42:47

单链表的实现

  • 什么是单链表
    • 单链表的结构图讲解
      • 创建链表
      • 打印链表
      • 尾插链表
      • 尾删链表
      • 头插链表和头删链表
      • 查询链表
      • 特定位置插入
      • 特定位置删除
      • 销毁链表
  • 总结

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

什么是单链表

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

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

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

回想一下我们在实现顺序表的时候,是通过“下标(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断言一下空表的情况。
在这里插入图片描述

查询链表

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

特定位置插入

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

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

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

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

特定位置删除

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

销毁链表

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

总结

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

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

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

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

相关文章

题库API调用详细教程

题库API调用详细教程 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 查题校园题库:查题校园题库后台(点击…

洛谷千题详解 | P1010 [NOIP1998 普及组] 幂次方【C++、Java、Python、Pascal语言】

博主主页:Yu仙笙 专栏地址:洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析: C源码: Pascal源码: Java源码: Python源码: ------------------------------------------------…

C#基础:类class与结构struct的区别

一、类class 类class是引用类型,可以直接赋值为null,默认值也是null XClass xClass null;//语法正确 一般来说,某个类对象使用另一个类的对象赋值时,则两者共用一个内存地址【节约内存空间】,ReferenceEquals引用比…

JDK的安装-详细版

大家好,我是研究大数据领域的 查德-常,大数据是一个随着数据量快速增长而应运而生的行业,让我来带你了解大数据吧。 JDK的安装JDK安装1.1 搜索jdk1.2 登录Oracle1.3 安装jdk1.4 环境配置1.5 验证是否安装好jdk由于粉丝中初学者比较多&#xf…

《web课程设计》用HTML CSS做一个简洁、漂亮的个人博客网站

🎉精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: ​​【主页——🚀获取更多优质源码】​​ 🎓 web前端期…

西祠胡同社区彻底消失

我是卢松松,点点上面的头像,欢迎关注我哦! 今天打开西祠胡同,发现网站备案注销了,域名(www.xici.net)停止解析了,半年前1元转让股权的事也不了了之,西祠胡同就这样静悄悄的消失了,连…

MongoDB 数据库(一):MongoDB的介绍与安装

目录一、MongoDB数据库的介绍与安装1.1 NoSQL数据库简介1.2 MongoDB 简介1.2.1 再议业务应用场景1.2.2 为什么要使用 MongoDB1.2.3 适用场景二、安装和使用MongoDB客户端2.1 Windows 安装 MongoDB2.2 Linux-Centos7 安装 MongoDB2.3 安装Studio 3T一、MongoDB数据库的介绍与安装…

PyCharm连接远程Docker环境

1. docker 配置 使用-p参数暴露一个端口用于ssh连接。 docker run -itd --name wangchao_paddle --gpus all -p 8899:8888 -p 8822:22 -v /data:/root/data registry.baidubce.com/paddlepaddle/paddle:2.3.0-gpu-cuda10.2-cudnn7 /bin/bash如果镜像没有ssh则需要先安装。&am…

后台获取不到请求头中token信息的解决方法

前言 项目要做单点登录功能,于是在shiro的基础上加入了自定义的 Filter,使用 JWT 自定义生成和校验token信息。 功能写好后自己在 postman 中测试了效果,将 token 放在 Headers 中请求后台接口(如下图,还没发现问题&…

【微服务】基于Ribbon实现负载均衡

前言 我们在上篇文章中讲解了如何通过Nacos实现服务治理,由此引发的负载均衡的问题。这篇文章就介绍一个SpringCloud alibaba的另一个组件:Ribbon,如何通过Ribbon实现负载均衡。 负载均衡 什么是负载均衡? 通俗的讲&#xff0…

C语言学习笔记

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录前言C的面向过程和C的面向对象1.C的数据类型与常量2.C中的变量1、什么是变量?2、变量名字的命名规则&#…

openlayer 加载4547坐标系 以及 wfs服务数据(或其他坐标系)

1.首先查看坐标系基础信息如范围等:如下图: 2.若将地图设置成4547坐标系: 核心代码: proj4.defs("EPSG:4547","projtmerc lat_00 lon_0114 k1 x_0500000 y_00 ellpsGRS80 unitsm no_defs typecrs");register…

ModelBox姿态匹配:抖抖手动动脚勤做深呼吸

摘要:本案例使用Windows版本的ModelBox SDK进行二次开发,主要是针对姿态匹配案例开发实践。本文分享自华为云社区《姿态匹配:抖抖手动动脚勤做深呼吸》,作者:吴小鱼。 在之前发布的AI说ModelBox推理真的高效吗一文中&…

对于含有琥珀酰亚胺酯的叠氮试剂Azidoacetic Acid NHS Ester,N3-C5-NHS ester,N3-C3-NHS ester 知识分享

本文重点为大家总结关于含有琥珀酰亚胺酯基团的叠氮基相关试剂的性质特点,西安凯新生物科技有限公司​主要从Azidoacetic Acid NHS Ester、N3-C5-NHS ester、N3-C3-NHS ester进行分享。 一、Azidoacetic Acid NHS Ester CAS:824426-32-6 中文名&#xff…

Linux shell脚本之回顾及实用笔记

一、前言 我们从事运维的小伙伴,除了自动化运维外,在没有自动化条件下,借助shell脚本/Python脚本来提升运维效率,无疑是一个必选项,当前也可以自建自动化运维平台,我们这里还是以Linux shell脚本为主,来汇总一些常用的运维脚本,对于有基础的同学,也随本文一起回顾下相…

【学习笔记】《模式识别》2:聚类分析

聚类分析 文章目录聚类分析一、聚类分析的概念二、相似性的测度1.距离的四条基本公理2.欧氏距离(Euclid,欧几里得)--距离3.马氏距离(Maharanobis)4.马氏距离与欧氏距离之间的关系5.明氏距离(Minkowaki)6.汉…

4款实用的黑科技软件,白嫖党最爱,功能强大到离谱

闲话少说,直上干货。 1、Dism 这是一款国人研发,免费又好用的电脑优化工具,备受全球电脑爱好者追捧,它解决了系统安装与维护两大痛点问题——自定义设置与优化,相当于给电脑请了免费“保姆”。从系统安装到调校&#x…

LabVIEW基础-VI Scripting

文章目录使用过程前面板界面修改属性节点VI属性无输入时默认当前VI。输入VI引用的静态方法输入VI引用的动态方法获取对象引用从VI获取前面板所有控件的引用设置修饰物的前景色获取选项卡1上所有的数值控件并设置标签前景色从VI获取前面板选项卡的引用-转换为特定的类-获取选项卡…

B+树的插入、删除和分裂,注意国内教材和国外的对于B+树的定义的不同

B树 1 国内教材上B树的定义 一棵 m 阶的B树满足 (考研教材): 每个非叶子结点最多有 m 棵子树(孩子结点)根结点至少有2棵子树 (1层除外),非叶结点至少有 m/2 (向上取整) 棵子树结点的子树的个数与关键字的个数相等: 介于 m/2 (向…

DSL查询文档

目录一、DSL查询语法二、DSL查询分类全文检索查询精确查询地理坐标查询复合查询复合查询——fuction score复合查询——Boolean Query三、搜索结果处理排序分页高亮一、DSL查询语法 DSL Query基本语法 查询成功 二、DSL查询分类 DSL Query的分类 Elasticsearch提供了基于…