一篇博客读懂单链表——Single-List

目录

一、初识单链表

单链表是如何构造的:

单链表如何解决顺序表中的问题:

二、单链表的初始定义 

三、尾插和头插

3.1 新建结点CreateNode

3.2 打印SLTPrint

3.3 尾插SLTPushBack 

3.4 头插SLTPushFront 

四、尾删和头删

4.1 尾删SLTPopBack

4.2 头删SLTPopFront

五、某位置前插入删除

5.1 查找SLTFind

5.2 某位置前插入SLTInsert

5.3 某位置删除SLTErase

六、某位置后插入删除

七、 assert断言 

7.1 SLTPrint断言

7.2 SLTPushBack 和 SLTPushFront 断言

7.3 SLTPopBack 和 SLTPopFront 断言

7.4 SLTInsert 和 SLTErase 断言


顺序表的问题:

1.尾部插入效率还不错,头部或者中间插入删除,需要挪动数据,效率低下

2. size 满了后只能扩容,扩容是有一定消耗的;扩容一般存在一定的空间浪费

我们总结了顺序表的问题,下面我们学习的单链表就可以让这些问题迎刃而解。 

学习要求:掌握C语言的指针、二级指针、动态开辟内存的知识

一、初识单链表

我们首先来回顾一下顺序表中的结构体成员:

顺序表中单个结构体存储着顺序表的表头指针、整个顺序表的数据容量、实际存储的数据容量......

单链表是如何构造的:

链表每个结点会存储一个数据,同时会存储一个指针,这个指针指向下一个结点。

单链表如何解决顺序表中的问题:

链表的每一个结点都是 malloc 出来的,他们的地址并不是连续分配的,如果从头部或者中间插入删除,只需要改动单个结点,无需挪动整个 table ;因为链表的结点是一个一个开辟的,所以也不存在顺序表的空间浪费。

下面我们来看一下链表实际的结构:

在这里我们强调不需要太过于关注链表的物理结构,我们的注意点应该集中在其是个结构体。

二、单链表的初始定义 

这里还是和顺序表一样的套路,把它当成一个工程去做,当然就要分文件啦。

其次,在 .h 文件中我们要做我们的准备工作:

 接下来我们来看一下我们需要对链表做的操作:

三、尾插和头插

在学习尾插之前,我们需要先思考一个问题,为什么在我们的操作中有时候需要传指针而有时候需要传二级指针呢(下面以尾插为例)?

如果要探索这个问题的答案,我们一定要知道我们在尾插时是需要改变指针的值的。如果我们调用函数需要改变 int 的值,我们是不是需要传 int* 来改变我们的实参,而在这里我们需要改变的是SLTDataType* 的值,所以就需要我们传入指针的地址来对指针的值进行修改。

3.1 新建结点CreateNode

 我们在这还需要写一个函数,这个函数可以说是链表插入元素的精髓了,我们在前面了解到了链表插入元素是一个结点一个结点地 malloc 出来的,所以我们在这里写一个 CreateNode 函数来创建我们的新结点,可以极大地减少我们下面的代码量。

3.2 打印SLTPrint

为了方便后续的检测,我们也要先把显示链表内容的函数定义出来:

3.3 尾插SLTPushBack 

3.4 头插SLTPushFront 

这里要注意的是我们先让 NewNode 作为头结点来指向 *pphead (即phead) 以此来找到之前第一个结点的地址,然后我们再将 *pphead 指向 NewNode,在以后遇到需要头插的题目,我们也要使用这种顺序。

四、尾删和头删

4.1 尾删SLTPopBack

尾删肯定要找到最后一个元素,让指向最后一个元素的指针直接指向 NULL ,然后再 free 掉最后一个结点,再查找会后一个结点时,我们需要改变的是指向它地址的指针的值,所以我们就要用 tail->next->next != NULL 作为寻找条件:

欸,我们从图中和代码中不难发现,当 tail 的后两个元素为 NULL 时才能进行判断,那么如果链表中只有一个结点(tail->next == NULL),这时候应该怎么办呢?当然是单独进行判断啦!

下面我们来看一下完整代码:

但是需要注意的是,如果我们在一开始就定义了 tail 指针指向 *pphead ,当 tail == NULL 时, free 掉 tail ,这样的写法在我们删掉最后一个结点时会在 Print() 函数中报错,错误代码如下:

这是为什么呢?原因是如果提前用 tail 接收 *pphead,那么在 free(tail) 后也应该将 *pphead 置为空,如果仅仅将 tail 置空,那我们的 *pphead 就成了野指针,这样当然是不可取的。

4.2 头删SLTPopFront

头删就相对简单很多,只需要改变 *pphead 的指向,再 free 就好。

 

五、某位置前插入删除

在学习某位置插入删除前,我们需要知道的是我们的“某位置”应该如何定位,比较某个结点与我们的目标值?显然是不行的,当有多个结点的值重复时这个想法自然就会被推翻,那我们应该怎么办呢?我们也要设计一个查找函数,将第一个查找到的结点地址返回,再将该地址传入我们的插入删除函数中。

5.1 查找SLTFind

当我们遍历完整个链表却没找到想要的元素时,说明链表中没有该元素,返回 NULL 。

5.2 某位置前插入SLTInsert

首先我们要判断这里是不是头插,如果是头插,我们直接调用头插函数,如果不是,我们继续我们的移形换影大法,插入结点。 

 

在改变 cur->next 前,我们要用临时变量 tmp 接收 cur 下一个结点的地址,这样才能在后面找到。 

5.3 某位置删除SLTErase

因为我们的 SLTFind 函数可以定位到 val==x 的当前结点,所以我们可以用这一特点删除指定位置的元素。当我们要删除的是第一个结点时,我们同样可以调用头删函数。

 

 

六、某位置后插入删除

这里思路比较简单,我们来简单看一下代码:

七、 assert断言 

最后我们当然不能忘记断言,下面我们一起来看看每个函数中需要的断言:

7.1 SLTPrint断言

SLTPrint不用断言,因为我们已经设置了当链表为空时只需打印 NULL

7.2 SLTPushBack 和 SLTPushFront 断言

这两个函数只需要断言 pphead 这个二级指针,因为我们是允许链表为空时的头插尾插的。

7.3 SLTPopBack 和 SLTPopFront 断言

这两个函数不仅要断言 pphead 还要断言 *pphead ,因为当链表中有结点时才可以Pop

7.4 SLTInsert 和 SLTErase 断言

插入和删除函数不仅需要像上面两个函数一样断言 pphead *pphead ,还要断言 pos

下面是我的单链表源代码库,包含了对每个函数测试用的代码,需要的uu可以自行查看:

手撕单链表 - Gitee.com

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

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

相关文章

hub.docker访问不了的问题(一步解决)

暂时我也不清楚,但是下面这个网址可以用(可以先用着)Docker Hub Container Image Library | App Containerization (axlinux.top)https://hub.axlinux.top/

Testng XML文件

目录 概述 XML各部分介绍 概述 当你使用TestNG测试框架时,你可以使用XML文件来配置和运行测试套件。XML文件中包含了测试类、测试方法、测试参数等配置信息,使你能够更灵活地组织和管理测试。 以下是一个简单的TestNG XML文件的例子: &l…

设计模式中的静态工厂,到底解决了什么问题?

设计模式中的静态工厂,到底解决了什么问题? 文章目录 设计模式中的静态工厂,到底解决了什么问题?一、基本说明二、代码演示1、名称更明确2、不必每次调用都创建新对象3、返回接口类型4、降低客户端和具体实现之间的耦合5、参数化实…

Maya 2024 for Mac(3D建模软件)

Maya 2024是一款三维计算机图形软件,具有强大的建模、动画、渲染、特效等功能,广泛应用于影视、游戏、广告等行业。以下是Maya 2024软件的主要功能介绍: 建模:Maya 2024具有强大的建模工具,包括多边形建模、曲面建模、…

数据可视化在监控易中的艺术与实践

在数字化运维管理中,数据可视化成为一种日益重要的工具,它将复杂的数据通过图形化的方式呈现,帮助运维团队更加直观和快速地理解系统的运行状况。监控易(MeiXin Era)将数据可视化引入到运维监控中,通过科学…

浅谈Elasticsearch 文档操作

Elasticsearch 文档操作 Elasticsearch 是一个基于 Lucene 的分布式搜索引擎,它提供了全文搜索、结构化搜索、分析等功能。在 Elasticsearch 中,文档操作是一个重要的功能,包括文档的索引、更新、删除以及批量操作。本文将详细介绍 Elastics…

【工程实践】Docker使用记录

前言 服务上线经常需要将服务搬到指定的服务器上,经常需要用到docker,记录工作中使用过dcoker指令。 1.写Dockerfile 1.1 全新镜像 FROM nvidia/cuda:11.7.1-devel-ubuntu22.04ENV WORKDIR/data/Qwen-14B-Chat WORKDIR $WORKDIR ADD . $WORKDIR/RUN ap…

洗地机是智商税吗?洗地机有没有必要买?2023洗地机推荐

传统的扫地拖地方式不仅时间长,被毛孩子和萌娃制造的顽固污渍更是让人头痛不已,高效又有效的地面清洁方式成了我们最大的诉求。目前洗地机受到青睐,异常火爆,也成为一众清洁扫地的选择之一,那洗地机到底是不是智商税呢…

C语言从入门到精通之【printf和scanf函数】

printf()是输出函数,scanf()是输入函数,但是它们的工作原理几乎相同。两个函数都使用格式字符串和参数列表。 printf()函数的格式 printf( 格式字符串, 待打印项1, 待打印项2,…);待打印项1、待打印项2等都是要打印的项。它们可以是变量、常量&#xff…

业务出海之服务器探秘

这几年随着国内互联网市场的逐渐饱和,越来越多的公司加入到出海的行列,很多领域都取得了很不错的成就。虽然出海可以获得更加广阔的市场,但也需要面对很多之前在国内可能没有重视的一些问题。集中在海外服务器的选择维度上就有很大的变化。例…

使用validator实现枚举类型校验

使用validator实现枚举类型校验 前言: 在前端调用后端接口传递参数的过程中,我们往往需要对前端传递过来的参数进行校验,比如说我们此时需要对用户的状态进行更新,而用户的状态只有正常和已删除,并且是在代码中通过枚…

react ts实现一个 无限加载组件

页面滑动到底部,直接加载下一页数据 InfiniteScroll.tsx /*** 无限 加载组件*/import { FC, createRef, useEffect, CSSProperties } from react import LoadingText from ../LoadingTexttype PropsType {loadMore: () > voidhasMore: boolean }const Infinit…

【华为云IaaS基础三件套之----计算ECS、网络EIP、存储EVS】

MD[华为云IaaS基础三件套----计算、网络、存储] 华为云IaaS基础三件套之----计算ECS、网络EIP、存储EVS 说明: 这里只是简单从计算/网络/存储,进行介绍,阐明云上对于云下的优势;因ECS是三者综合,故最后说明。 1.网络----弹性公…

STM32 HAL库多路PWM没有输出踩坑记录

之前只弄过单路的,这次想用4路PWM,CUBE里面一顿配置,生成,然后套用之前的代码: HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); 这算是开启第一路了,心想后面无非就复制几条,改下通道的事了&…

算法----删掉一个元素以后全为 1 的最长子数组

题目 给你一个二进制数组 nums ,你需要从中删掉一个元素。 请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。 如果不存在这样的子数组,请返回 0 。 提示 1: 输入:nums [1,1,0,1] 输出&…

Day02_《MySQL索引与性能优化》

文章目录 一、SQL执行顺序二、索引简介1、关于索引2、索引的类型Btree 索引Btree 索引 三、Explain简介四、Explain 详解1、id2、select_type3、table4、type5、possible_keys6、key7、key_len8、ref9、rows10、Extra11、小案例 五、索引优化1、单表索引优化2、两表索引优化3、…

安装 Lua 的 HTTP 库

首先,你需要安装 Lua 的 HTTP 库。可以使用 LuaRocks 来安装。以下是安装命令: luarocks install http然后,你可以使用以下代码来爬取网页内容: local http require http-- 设置代理信息 http.set_proxy(jshk.com.cn)-- 网页UR…

灵活运用Vue指令:探究v-if和v-for的使用技巧和注意事项

🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 ⭐ 专栏简介 📘 文章引言 一、作…

为什么打开idea时,没有启动页面,如何解决?

更新idea2021.2后,当双击idea打开时,发现没有启动界面,直接进入IDEA界面,中间等待时间,让人误以为没有打开idea成功,使得多次点击idea图标。 解决方案就是 在idea界面菜单栏中找到帮助(Help)&a…

全域全自主建设,亚信科技AntDB数据库助力广电5G业务上线运行

自2019年6月,中国广电成功获得5G牌照以来,迅速推进网络建设目标,成为5G网络覆盖广、应用场景多、用户体验出色的第四大运营商。其依托全球独有的700MHz频谱资源,具备覆盖能力强、容量足、速率高的优势。通过不断深化和中国移动的共…