c语言,单链表的实现----------有全代码!!!!

news/2024/5/21 19:15:35

1.单链表的定义和结构

单链表是一种链式的数据结构,它用一组不连续的储存单元存反线性表中的数据元素。链表中的数据是以节点的形式来表示的,节点和节点之间相互连接

一般来说节点有两部分组成 1.数据域 :数据域用来存储各种类型的数据(浮点数,字符串,自定义类型的数据),2.指针域: 指针域用来存储的是指针,它用来指向下一个节点

 2.单链表的实现

SLlist.h

//定义单链表的节点
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType Data;struct SListNode* next;//指向下一个节点的指针
}SLTNode;//增加新的节点
SLTNode* SLTBuyNode(SLTDataType x);//打印链表
void SLTPrint(SLTNode* phead);//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);//尾删
void SLTPopBack(SLTNode** pphead);//头删
void SLTPopFront(SLTNode** pphead);//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SListDesTroy(SLTNode** pphead);

SLlist.c

//增加新的节点
SLTNode* SLTBuyNode(SLTDataType x) {//开辟一个节点大小的空间SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->Data = x;newnode->next = NULL;return newnode;
}//打印链表
void SLTPrint(SLTNode* phead) {//循环打印,当phead指向NULL(也就是尾节点指向的下一个节点)时停止while (phead){printf("%d->", phead->Data);//让phead指向下一个节点,并赋值给pheadphead = phead->next;}printf("NULL\n");
}//尾插
//想要修改值就要传地址,不能传值。而phead是个指针,我们要拿二级指针接收
void SLTPushBack(SLTNode** pphead, SLTDataType x) {assert(pphead);//*pphead说明第一个节点为NULL也就是说链表为空if (*pphead == NULL) {*pphead = SLTBuyNode(x);    //直接创建一个新的节点}//链表不为NULL时尾插else{SLTNode* ptail = *pphead;    //创建一个节点,从头开始遍历找尾节点//遍历链表,找到尾节点while (ptail->next)    //下一个节点为NULL表达式为假,就说明已经找到了尾节点{ptail = ptail->next;}ptail->next = SLTBuyNode(x);   //找到为节点,让尾节点指向新的节点,完成尾插}}//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x) {assert(pphead);SLTNode* newnode = SLTBuyNode(x);    //创建一个新的节点准备进行头插newnode->next = *pphead;      //直接让新节点指向原先的第一个节点*pphead = newnode;            //让新的节点成为新的第一个节点//在是有一个节点的情况下也可以完美完成任务
}//尾删
//可能要修改第一个节点,所以得传地址,用二级指针** pphead接收
void SLTPopBack(SLTNode** pphead) {//列表不能为NULL不然删啥assert(pphead && *pphead);SLTNode* ptail;    //找尾节点SLTNode* prev;    //尾节点前一个节点,它将来可能是新的尾节点prev = ptail = *pphead;//只有一个节点,直接删除不用找尾节点前面的节点if (ptail->next == NULL){//改变头节点需要用到pphead,对它进行解引用得到原第一个节点free(*pphead);*pphead = NULL;}//有一个以上的节点,开始找尾节点,进行尾删else{//当 某个节点的下一个节点(指向)->NULL 时找到尾节点while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);    //找到了原尾节点直接释放ptail = NULL;   prev->next = NULL;    //让新的位节点(指向)->NULL}
}//头删
//肯定会修改到第一个节点,要传地址,拿二级指针** pphead接收
void SLTPopFront(SLTNode** pphead) {assert(pphead && *pphead);SLTNode* ptail = *pphead; //记录原第一个节点//改变原第一个节点*pphead = ptail->next;   //让第二个节点成为,新的第一个节点//直接释放原第一个节点free(ptail);ptail = NULL;
}//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x) {//空链表的话不用找了assert(phead);SLTNode* pcur = phead;//让pcur遍历链表,直到尾节点指向的下一个节点NULL,说明没有这个元素while (pcur){if(pcur->Data == x){return pcur;    //有这个元素,直接返回这个元素所在节点的地址}pcur = pcur->next;}return NULL;
}//在指定位置之前插入数据
//可能会改变第一个节点要传地址,拿二级指针** pphead接收
//pos 为指定位置
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) {assert(pphead);//创新的节点SLTNode* newnode = SLTBuyNode(x);SLTNode* prev = *pphead; //prev用找到pos之前的位置//如果只有一个节点,会出现prev找不到pos的情况,因为一开始这两的位置一样,prev的下一个位置永远不可能是posif (pos == prev) {SLTPushFront(pphead, x);}//有多个节点的情况,开始找pos节点并再此之前插入else {//找pos之前的节点prevwhile (prev->next != pos){prev = prev->next;}//拿1 -> 2 -> NULL 我们要在1(prev) 2(pos)之间插入3演示newnode->next = pos;     //先让新的节点,指向pos   3 -> 2 ->NULLprev->next = newnode;    //在让prev节点指向新的节点  1 -> 3 -> 2 ->NULL}    
}//在指定位置之后插入数据
//不存在改变第一个节点的情况,传第一个节点值过来就够用
void SLTInsertAfter(SLTNode* pos, SLTDataType x) {//指定的位置不能为NULL,要不然谁知道你想要在谁之后插入数据assert(pos);创建新的节点SLTNode* newnode = SLTBuyNode(x);SLTNode* del = pos->next;  //del为pos之后的节点//如果只有一个节点,那么pos指向的下一个节点为NULL,这套逻辑依旧适用//拿1 -> 2 -> 3 -> NULL 我们要再2(pos)3(del)之间插入4newnode->next = del;  //先让新的节点指向del   4 ->3 -> NULLpos->next = newnode;  //在让pos指向新的节点   1 -> 2 -> 4 -> 3 -> NULL}//删除pos节点
//如果删除的是第一点,得传地址,因为第一个节点会发生变化
void SLTErase(SLTNode** pphead, SLTNode* pos) {//链表不能为NULL不然删啥assert(pphead && pos && *pphead);SLTNode* del = pos->next;   //del为pos之后的节点SLTNode* prev = *pphead;    //prev为pos之前的节点//如果只有一个节点,直接删即可,不用去找pos前一个节点,这样找找不到if (pos == del)//pos = del 我搞错了,这样就赋值了{//头删,传头结点的地址也就是ppheadSLTPopFront(pphead);}//不止一个节点,找pos之前的节点prevelse{while (prev->next != pos){prev = prev->next;}//把pos前一个节点prev和后一个节点del连接起来,在把pos节点释放prev->next = del;free(pos);pos = NULL;}
}//删除pos之后的节点
//第一个节点不可能被修改,因为即使只有一个节点,第一个节点后面的节点也是NULL
void SLTEraseAfter(SLTNode* pos) {//pos后面的节点不能为NULL不然删啥assert(pos && pos->next);SLTNode* del = pos->next;    //del为pos之后的节点//1->2->3,让1跟3连接起来,在释放2pos->next = del->next;free(del);del = NULL;
}//销毁链表
//涉及修改第一个,需要接收头结点地址
void SListDesTroy(SLTNode** pphead) {assert(pphead && *pphead);SLTNode* pcur = *pphead;     //pcur用来遍历链表,依次销毁SLTNode* next;     //next为当前需销毁节点的下一个节点,不然直接销毁就找不到下一个节点了//如果pcur为NULL,说明走到了尾节点指向的NULL,链表销毁完毕while (pcur){next = pcur->next;	//先保存当前需要销毁节点的下一个节点的地址free(pcur);         //销毁当前节点pcur = next;        //走向下一个节点}*pphead = NULL;    //让第一个节点为NULL,链表销毁完毕后为NULL
}


http://www.mrgr.cn/p/35526828

相关文章

这些Git事故灾难, 你经历过几个?

在大规模的协作中, git pull和push是远远不够使用的. 笔者介绍了自己在一线的工作中遇到了各种事故现场, 以及相应的解决方案. 快进来学习下, 也许以后用得上.前言 关于Git, 相信大家最常用的就是pull和push. 但随着协作规模的提升, 遇到的问题也会越来越多. 本篇文章并不科普一…

Ranorex无法使用spy识别element(只能识别外部container) --针对edge浏览器

1.问题 问题如标题,这是一个很严重的问题,表明我们不仅不能通过track识别元素,更重要的是spy无法识别UI元素,就会导致我们无法通过自动化脚本来控制UI元素,实现自动化测试!!! 2.解决 2.1 确保不要同时开启两个Chrome用例(chorme或者edge) 2.2 可以开启 Internet Explorer 模式(…

秋叶Stable diffusion的创世工具安装-带安装包链接

来自B站up秋葉aaaki,近期发布了Stable Diffusion整合包v4.7版本,一键在本地部署Stable Diffusion!! 适用于零基础想要使用AI绘画的小伙伴~本整合包支持SDXL,预装多种必须模型。无需安装git、python、cuda等任何内容&am…

SAP在中国的合作伙伴有哪些?

SAP作为一家全球领先的企业管理解决方案供应商,深受全球各行各业各规模企业的信赖。SAP拥有超过40年的专业经验,被称为ERP系统的“最后一道防线”。无论是面向中小型企业的Business one,还是面向中、大型集团的S/4HANA,不同规模、行业的企业都能从SAP的多样化企业管理解决方…

ubuntu安装python3.10

1. 官网下载源程序 2. 解压进入文件夹: ./configure --prefix/usr/local/python3/ 3. 编译安装: make && make install 4. 添加环境变量: vim ~/.bashrc PATH/usr/local/python3/bin:$PATH #保存后,刷新配置文件 sour…

EQ-BDS面板部署机器人

一、机器人配置教程 0.预处理 首先处理杀毒软件误报问题。在服务器上安装火绒安全当然,您也可以不选择火绒,使用其他杀毒软件,到时候给插件加上信任即可安装完成后禁用Windows Defender,详见EQ-BDS面板用户手册 1.下载然后解压压缩包 点我跳转到下载页面 这个网盘不需要开会…

探索设计模式的魅力:融合AI大模型与函数式编程、开启智能编程新纪元

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 ✨欢迎加入探索AI大模型与函数式编程模式融合之旅✨ 在编程世界的广阔疆域里,两大…

基于ChatGPT打造安全脚本工具流程

基于ChatGPT打造安全脚本工具流程前言 以前想要打造一款自己的工具,想法挺好实际上是难以实现,第一不懂代码的构造,只有一些工具脚本构造思路,第二总是像重复造轮子这种繁琐枯燥工作,抄抄改改搞不清楚逻辑,想打造一款符合自己工作的自定义的脚本工具难度倍增,但是随着AI…

-sh: ./example: No such file or directory

接上文的问题,咨询了隔壁部门的技术大佬后,认为是使用的交叉编译工具太旧了。因此在ARM官网重新下载工具包:下载到虚拟机后配置,完成后运行source命令使配置生效: source /etc/profile 重新编译目标代码并下载到开发板后运行:看到编译输出,已经能够找到文件了,只是缺少…

lua基本语法

Lua语法入门 初识lua vi hello.lua print("hello,lua") lua hello.lua 变量和循环 变量 循环 条件控制、函数 条件控制

RocketMQ 之 IoT 消息解析:物联网需要什么样的消息技术?

作者:林清山(隆基) 前言: 从初代开源消息队列崛起,到 PC 互联网、移动互联网爆发式发展,再到如今 IoT、云计算、云原生引领了新的技术趋势,消息中间件的发展已经走过了 30 多个年头。 目前&a…

Mybatis-plus中的分页操作

Mybatis-plus中的分页操作 1.导入Mybatis-plus依赖2.创建mybatis配置类3.参数 1.导入Mybatis-plus依赖 因为是一个springboot项目&#xff0c;其中的pom.xml文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns&q…

个人项目作品集

前言 个人博客地址: Lovi* - 博客园 (cnblogs.com) 后端代码地址:Lovi (shenqing0202) - Gitee.com 前端代码地址:Lovi-github (Lovi) Java相关项目 Servlet+jsp【热忱冰棒电子相册】 后端架构数据库表项目图片SSM+jsp【比赛抽签分组系统】 代码架构项目图片Springboot+vue…

Mac(M1)配置基于ARM64的Tensorflow

以下步骤最好先执行 conda config --remove-key channels 删除conda镜像源 pip config unset global.index-url 删除pip镜像源 然后接下来的步骤最好挂上梯子。 1.下载miniforge:从https://github.com/conda-forge/miniforge上找到arm64(Apple Silicon)版本进行下载,下一步…

2024 CVPR AIGC集合

完全外行&#xff0c;不建议参考 一、3D重建 PointAvatar: Deformable Point-based Head Avatars from Videos 对原始颜色进行解纠缠&#xff0c;得到固有反射和相关阴影。 基于可变形点云对表情、颜色、位置等信息进行建模。 总结&#xff1a;可以看作是对局部像素的分解与扩…

YOLOv8 测试 5:Linux 中 Docker 部署 YOLOv8,Python 封装 API 接口,base64 图片处理

一、前言 记录时间 [2024-4-14] 系列文章简摘&#xff1a; Docker 学习笔记&#xff08;二&#xff09;&#xff1a;在 Linux 中部署 Docker&#xff08;Centos7 下安装 docker、环境配置&#xff0c;以及镜像简单使用&#xff09; API 接口简单使用&#xff08;二&#xff09;…

EasyPoi表格导入添加校验

EasyPoi表格导入添加校验 项目添加maven依赖实体类自定义校验controller测试结果 代码地址 项目添加maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www…

IfcDoorPanelOperationEnum

IfcDoorPanelOperationEnum 类型定义该列举定义了各个门板的基本操作方式,如图所示。EnumeratorIllustrationSwinging DoubleActing Sliding Folding Revolving Rollingup FixedPanel UserDefinedNotDefinedFigure — Door operations 门板的打开方向由IfcDoor的局部位置决定。…

Python案例:输出公元后到目前为止全部回文日期

一、回文日期 一个日期,如果顺读和倒读都一样,那么就称之为回文日期,比如今天:20211202,就是一个神奇的回文日期。 二、提出任务输出公元后的全部回文日期 要求每行输出五个回文日期 统计总共有多少个回文日期三、完成任务 (一)涉及知识点 1、time模块time模块有两个常用…