单链表原来是这样实现的!
文章目录
- 前言
- 1. 链表的概念及结构
- 1.1在链表里,每节“车厢”是什么样的呢?
- 1.2为什么还需要指针变量来保存下⼀个节点的位置?
- 2. 单链表的实现
- 1. 定义结构体`(Seqlist)`
- 2. 打印函数`(SLTPrint)`
- 小插曲,创建节点函数`CreateNode`
- 3. 尾插函数 `(SLTPushBack)`
- 4. 头插函数 `(SLTPushFront)`
- 5. 尾删函数(`SLTPopBack`)
- 6. 头删函数(`SLTPopFront`)
- 小插曲,pos查找函数` SLTFind`
- 7. “插入指定位置前”函数(`SLTInster`)
- 8.“删除指定位置后”函数
- 9.销毁单链表函数`SLTDestroy`
- 结语
前言
“我会定期分享我的学习经验,也欢迎大家留言和交流,让我们共同学习和进步!感谢大家的支持,让我们一起开启这段充满技术乐趣的旅程吧!”
1. 链表的概念及结构
概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的
链表的结构跟火车车厢厢相似,淡季时车次的车厢会相应减少,旺季时车次的车厢会额外增加几节。只需要将火车里的某节节厢去掉/加上,不会影响其他车厢,每节车厢都是独立存在的。
车厢是独里存在的,且每节车厢都有车门。想象⼀下这样的场景,假设每节车厢的车门都是锁上的状态,需要不同的钥匙才能解锁,每次只能携带⼀把钥匙的情况下如何从车头走到车尾?
最简单的做法:每节车厢里都放⼀把下一节车厢的钥匙。
1.1在链表里,每节“车厢”是什么样的呢?
与顺序表不同的是,链表⾥的每节"车厢"都是独立申请下来的空间,我们称之为“结点/节点”,节点的组成主要有两个部分:当前节点要保存的数据和保存下一个节点的地址(指针变量)。
图中指针变量 plist保存的是第⼀个节点的地址,我们称plist此时“指向”第⼀个节点,如果我们希望plist“指向”第⼆个节点时,只需要修改plist保存的内容为0x0012FFA0。
1.2为什么还需要指针变量来保存下⼀个节点的位置?
链表中每个节点都是独立申请的(即需要插⼊数据时才去申请⼀块节点的空间),我们需要通过指针
变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。
2. 单链表的实现
1. 定义结构体(Seqlist)
在SList.h头文件中
typedef int SLNDataType;
typedef struct SListNode
{SLNDataType val;struct SList* next;//这里只是指针,不是结构体
}SLNode;
2. 打印函数(SLTPrint)
注意下述代码皆是:
在SList.h头文件中定义函数
在SList.c文件中实现函数
在Test.c文件中函数测试
SeqList.h文件中
定义函数:
SList.c文件中
实现函数:
void SLTPrint(SLNode* phead) //打印单链表
{SLNode* cur = phead;while (cur != NULL){printf("%d->", cur->val);cur=cur->next;}printf("NULL");
}
小插曲,创建节点函数CreateNode
在实现下面的插入函数之前,还需要一个函数来开辟空间给新的节。
函数实现
SLNode* CreateNode(SLNDataType x) //新建节点,开辟空间
{SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->val = x;newnode->next = NULL;return newnode;
}
3. 尾插函数 (SLTPushBack)
定义函数:
实现函数:
void SLTPushBack(SLNode** pphead, SLNDataType x) //尾插
{SLNode* newnode = CreateNode(x);if (* pphead == NULL){*pphead = newnode;}else{SLNode* tail = * pphead; //找尾while (tail->next != NULL){tail = tail->next; //因为tail是局部变量,而tail->next是结构体,出来作用域tail就销毁了}tail->next = newnode; //所以这里把newnode赋值给tail->next}
}
函数测试:
int main()
{SLNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPrint(plist);return 0;
}
运行结果:
4. 头插函数 (SLTPushFront)
定义函数:
实现函数:
void SLTPushFront(SLNode** pphead, SLNDataType x) //头插
{ SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));newnode->next =* pphead;newnode->val = x;*pphead = newnode;
}
函数测试:
int main()
{SLNode* plist = NULL;SLTPushFront(&plist,520 );SLTPushBack(&plist,1);SLTPushBack(&plist,1);SLTPushFront(&plist,520);SLTPrint(plist);return 0;
}
运行结果:
5. 尾删函数(SLTPopBack
)
定义函数:
实现函数:
void SLTPopBack(SLNode** pphead) //尾删
{assert(pphead);assert(*pphead);if ((*pphead)->next== NULL){free(*pphead);*pphead = NULL;}else{SLNode* prev = NULL;SLNode* tail = *pphead;while (tail->next != NULL){prev = tail;tail = tail->next;}free(tail);tail = NULL;prev->next = NULL;}
}
函数测试:
int main()
{SLNode* plist = NULL;SLTPushFront(&plist,520 );SLTPushBack(&plist,1314);SLTPushBack(&plist,00544);SLTPopBack(&plist);SLTPrint(plist);return 0;
}
运行结果:
6. 头删函数(SLTPopFront
)
定义函数:
实现函数:
void SLTPopFront(SLNode** pphead) //头删
{assert(*pphead);SLNode* tail = *pphead;tail = tail->next;free(*pphead);*pphead = tail;
}
函数测试:
int main()
{SLNode* plist = NULL;SLTPushFront(&plist,5201314);SLTPushBack(&plist,00544);SLTPushBack(&plist,44944);SLTPopFront(&plist);SLTPrint(plist);return 0;
}
运行结果:
小插曲,pos查找函数 SLTFind
用来确定pos位置,方便后面调用
实现函数:
SLNode* SLTFind(SLNode** pphead, SLNDataType x) //pos的查找函数
{assert(pphead);SLNode* cur = *pphead;while (cur){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}
7. “插入指定位置前”函数(SLTInster
)
定义函数:
实现函数:
void* SLTInster(SLNode** pphead, SLNode* pos, SLNDataType x) //指定位置前面插入
{assert(pos);assert(pphead);assert(*pphead);SLNode* node = CreateNode(x);if (*pphead == pos){node->next = *pphead;*pphead = node;}SLNode* cur = *pphead;while (cur->next != pos){cur = cur->next;}cur->next = node;node->next = pos;
}
函数测试:
int main()
{SLNode* plist =NULL;SLTPushBack(&plist,1);SLTPushBack(&plist,2);SLTPushBack(&plist,3);SLNode* Find = SLTFind(&plist, 3);SLTInster(&plist,Find,123);SLTPrint(plist);return 0;
}
运行结果:
如同在第一个值为3的节点前面插入了123;
8.“删除指定位置后”函数
定义函数:
实现函数:
void* SLTEraseAfter(SLNode* pos) //指定位置后面删除
{assert(pos && pos->next);SLNode* del = pos->next;pos->next = del->next;free(del);
}
函数测试:
int main()
{SLNode* plist =NULL;SLTPushBack(&plist,520);SLTPushBack(&plist,2);SLTPushBack(&plist,520);SLNode* Find = SLTFind(&plist, 2);SLTEraseAfter(Find);SLTPrint(plist);return 0;
}
运行结果:
如图在第一个值为520的节点后面删除了小3;
9.销毁单链表函数SLTDestroy
定义函数:
实现函数:
void SLTDestroy(SLNode** pphead) //销毁单链表
{assert(pphead);SLNode* cur= *pphead;while (cur){SLNode* next = cur;free(cur);cur = next;}*pphead = NULL;
}
测试函数:
int main()
{SLNode* plist =NULL;SLTPushBack(&plist,1);SLTPushBack(&plist,2);SLTPushBack(&plist,3);SLTDestroy(&plist);return 0;
}
结语
感谢您阅读我的博客,我希望您能从中获得一些启发和帮助。如果您喜欢这篇博客,请分享给您的朋友,也欢迎留下您的评论和反馈。您的支持是我继续分享和创作的动力。谢谢!希望我们能在未来的博客中再次相见。祝您一切顺利,期待与您再次相会!
相关文章:

单链表原来是这样实现的!
文章目录 前言1. 链表的概念及结构1.1在链表里,每节“车厢”是什么样的呢?1.2为什么还需要指针变量来保存下⼀个节点的位置? 2. 单链表的实现1. 定义结构体(Seqlist)2. 打印函数(SLTPrint)小插曲,创建节点函数CreateNode3. 尾插函…...

excel一个单元格换行方法
要是在同一个单元格内输入文字输入不下的话,我们是可以进行同一个单元格换行设置的,而且换行的方法也是有很多种,下面我们就一起来看一下有哪些方法吧。 excel一个单元格换行方法: 方法一: 1、我们可以直接按下alte…...

echart一键生成迁徙图
echart_move 介绍 echart迁徙图,选择起点和目的地生成迁徙图 软件架构 html echarts js 使用说明 将文件放到同一目录下打开index.html即可 默认是小飞机图标,如果想修改图标,将图片放到同一目录,如1.svg 代码修改为对应位…...
开发、测试、生产环境
开发环境:开发环境是程序猿们专门用于开发的服务器,配置可以比较随意, 为了开发调试方便,一般打开全部错误报告。简单讲就是项目尚且处于编码阶段,一般这时候会把代码放在开发环境中,不会放在生产环境中。 …...
红队攻防文库文章集锦
再救你一次,不要让欲望击溃你的意志 0.红队攻防 1.红队实战 红队攻防之特殊场景上线cs和msf CVE-2021-42287&CVE-2021-42278 域内提权 红队攻防之Goby反杀 红队攻防实战之钉钉RCE 红队攻防实战之从边界突破到漫游内网(无cs和msf) 红队攻防实战系列一之C…...

Vue框架学习笔记——键盘事件
文章目录 前文提要键盘事件(并不是所有按键都能绑定键盘事件)常用的按键不同的tab和四个按键keyCode绑定键盘事件(不推荐)Vue.config.keyCode.自定义键名 键码 神奇的猜想div标签和click.enterbutton标签和click.enter 前文提要 …...

Windows安装mysql8.0
官网地址:MySQL :: MySQL Community Downloads 选择相应版本信息下载 默认选择点击下一步 默认配置点击next 设置密码 默认配置...
Linux C++网络编程-王健伟
文章目录 1-1课程详细介绍1-2环境搭建详细介绍2-1nginx简介、选择理由、安装和使用2-2nginx整体结构、进程模型3-1学习nginx源码前的准备工作3-2nginx源码学法,终端和进程的关系说3-3信号的概念、认识、处理动作3-4Unix/Linux体系结构、信号编程初步3-5信号编程进阶…...

接收网络包的过程—— IP层->TCP层->Socket层
在 tcp_v4_rcv 中,得到 TCP 的头之后,我们可以开始处理 TCP 层的事情。因为 TCP 层是分状态的,状态被维护在数据结构 struct sock 里面,因而我们要根据 IP 地址以及 TCP 头里面的内容,在 tcp_hashinfo 中找到这个包对应…...
HTTP 响应头信息
HTTP 响应头信息 HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。 在本章节中我们将具体来介绍HTTP响应头信息。 应答头说明Allow服务器支持哪些请求方法(如GET、POST等)。Content-Encoding文档的编码(Encode&#x…...
Android获取原始图片Bitmap的宽高大小尺寸,Kotlin
Android获取原始图片Bitmap的宽高大小尺寸,Kotlin val options BitmapFactory.Options()options.inJustDecodeBounds trueval decodeBmp BitmapFactory.decodeResource(resources, R.mipmap.p1, options)//此时,decode出来的decodeBmp宽高并不是原始图…...
数据结构之数组:简介、特性与应用
文章目录 🌾引言🌾数组的定义与特性🌿数组的定义🌿数组的特性🌿数组的优缺点 🌾数组的应用场景🍁数组的基本应用🍁动态数组(Dynamic Array)🍁多维…...

Hexo 还是 Hugo?Typecho 还是 Wordpress?读完这篇或许你就有答案了!
Hexo 首先介绍的是 Hexo,这也是咕咕没买服务器之前折腾的第一个博客。 演示站点:https://yirenliu.cn 用的主题是 butterfly,想当年刚用的时候,作者还没建群,现在 qq 群都有上千人了,GitHub 上的星星数量也有 2.7k 了。 优点 如果你不想买服务器,但也想折腾一个博客,…...

ChatGPT重磅升级!集简云支持GPT4 Turbo Vision, GPT4 Turbo, Dall.E 3,Whisper等最新模型
在11月7日凌晨,OpenAI全球开发者大会宣布了 GPT-4的一次大升级,推出了 GPT-4 Turbo号称为迄今为止最强的大模型。 此次GPT-4的更新和升级在多个方面显示出强大的优势和潜力。为了让集简云用户能快速体验新模型的能力,我们第一时间整理了大会发…...

Oracle 中的操作符
1.union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序; SELECT * FROM emp WHERE sal < 1500 UNION SELECT * FROM emp WHERE sal BETWEEN 1000 AND 2000 order by 1 2.union All:对两个结果集进行并集操…...
python之UDP网络应用程序开发
文章目录 版权声明UDP网络应用程序开发UDP初识UDP知识要点socket类的使用UDP发送数据开发流程分析UDP服务客户端通信栗子UDP广播发送 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程序员或相关权利人所有。…...

中低压MOSFET 2N7002W 60V 300mA 双N通道 SOT-323封装
2N7002W小电流双N通道MOSFET,电压60V电流300mA,采用SOT-323封装形式。超高密度电池设计,适用于极低的ros (on),具有导通电阻和最大直流电流能力,ESD保护。可应用于笔记本中的电源管理,电池供电系统等产品应…...

kafka的设计原理
文章目录 1 Kafka简介2 Kafka的架构2.1 Kafka 一些重要概念2.2 工作流程2.3 副本原理2.4 分区和主题的关系2.5 生产者2.5.1 分区可以水平扩展2.5.2 分区策略 2.6 消费者2.6.1 消费方式2.6.2 分区分配策略 2.7 数据可靠性保证2.7.1 副本数据同步策略2.7.2 ACK 应答机制2.7.3 可靠…...

CANdelaStudio 使用教程5 编辑DID
文章目录 在哪编辑DID的分类编辑快照数据添加 DID 在哪编辑 DID的分类 编辑快照数据 添加 DID...

RESTful API 架构快速入门 Flask实现
RESTful 简介 1.1 为什么要使用 RESTful 架构? Representational State Transfer(REST)是一种面向资源的架构风格,广泛应用于网络服务的设计和开发。使用RESTful架构有以下几个优点: 简单性和可扩展性: RE…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...