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

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.rhkb.cn/news/312759.html

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

相关文章

Node Version Manager(nvm):轻松管理 Node.js 版本的利器

文章目录 前言一、名词解释1、node.js是什么?2、nvm是什么? 二、安装1.在 Linux/macOS 上安装2.在 Windows 上安装 二、使用1.查看可安装的node版本2.安装node3. 查看已安装node4.切换node版本5.其它 总结 前言 Node.js 是现代 Web 开发中不可或缺的一部…

不说成为Linux高级工程师,但成为合格的软件开发人员还是够了,一文深入浅出的精炼总结Linux核心知识点,掌握Linux的使用与高阶技巧

不说成为Linux高级工程师,但成为合格的软件开发人员还是够了,一文深入浅出的精炼总结Linux核心知识点,掌握Linux的使用与高阶技巧。 Linux 的学习对于一个程序员的重要性是不言而喻的。前端开发相比后端开发,接触 Linux 机会相对…

MyBatis-Plus详解(2.5W字+)

说明:该文档是鄙人学习记录的笔记,用于日常翻阅、复习、以及和朋友们讨论学习,如果广大读者朋友发现文章的纰漏、错误,请在评论区或私信提出,本人将积极探讨纠正!!! 一、MyBatis-Plu…

Git回滚版本并push到远端master

1、查看日志 git log 2、还原最近的版本 () --git reset --hard commit-id 如:git reset --hard d84da14bf2743683eca7a015f56114faaa344f42 3、覆盖分支版本 git push -f origin dev 回滚本地master完成后,将回滚后的代码push到远端master&#xf…

Redis(Windows版本下载安装和使用)

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

mac配置Jmeter环境

mac配置Jmeter环境 一、安装jmeter二、Jmeter目录结构三、汉化Jmeter四、改变主题外观五、jmeter安装第三方插件六、jmeter基础入门案例 一、安装jmeter 第一步先自行配置好电脑的jdk环境 1、官网下载jar包 https://jmeter.apache.org/download_jmeter.cgi 2、解压到软件你自己…

Git 安装和配置

下载 Git 网址: https://git-scm.com/download 安装 Git 双击安装包, 开始安装. 修改安装路径, 选择非中文无空格路径: 开始安装: 安装成功: 配置 Git 安装完成后, 在任意文件夹内, 右键, 可以显示两个 Git 选项, 就说明安装成功了.

JavaSE-13笔记【集合2(+2024新)】

文章目录 3.Map3.1 Map继承结构3.2 Map接口的常用方法3.3 遍历Map3.4 HashMap集合3.4.1 HashMap集合key的特点3.4.2 HashMap集合的key存储自定义类型3.4.3 哈希表3.4.3.1 哈希表的介绍3.4.3.2 哈希表的存储原理 3.4.4 存放在HashMap和HashSet集合key部分的元素必须同时重写hash…

Elasticsearch:从 ES|QL 到 PHP 对象

作者:来自 Elastic Enrico Zimuel 从 elasticsearch-php v8.13.0 开始,你可以执行 ES|QL 查询并将结果映射到 stdClass 或自定义类的 PHP 对象。 ES|QL ES|QL 是 Elasticsearch 8.11.0 中引入的一种新的 Elasticsearch 查询语言。 目前,它在…

【环境搭建】(五)Ubuntu22.04安装cuda_11.8.0+cudnn_8.6.0

一个愿意伫立在巨人肩膀上的农民...... 设备配置: 一、安装GCC 安装cuda之前,首先应该安装GCC,安装cuda需要用到GCC,否则报错。可以先使用下方指令在终端查看是否已经安装GCC。 gcc --version 如果终端打印如下则说明已经安装…

解构 和 展开运算符

解构 {name,age}obj 1. 数组解构 数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法&#xff0c;如下代码所示&#xff1a; <script>// 普通的数组let arr [1, 2, 3];// 批量声明变量 a b c// 同时将数组单元值 1 2 3 依次赋值给变量 a b clet [a, b, c] …

QGIS插件Geo-SAM使用(基于SAM半自动标注遥感图像)

0.Geo-SAM介绍 Geo-SAM是一个QGIS插件&#xff0c;旨在帮助人们在使用大尺寸地理空间栅格图像时有效地分割、描绘或标记地貌。Segment Anything Model &#xff08;SAM&#xff09; 是一个具有超能力的基础 AI 模型&#xff0c;但模型大小巨大&#xff0c;即使使用现代 GPU&am…

Web端Excel的导入导出Demo

&#x1f4da;目录 &#x1f4da;简介:✨代码的构建&#xff1a;&#x1f4ad;Web端接口Excel操作&#x1f680;下载接口&#x1f680;导入读取数据接口 &#x1f3e1;本地Excel文件操作⚡导出数据&#x1f308;导入读取数据 &#x1f4da;简介: 使用阿里巴巴开源组件Easy Exce…

【网络编程】web服务器shttpd源码剖析——命令行和文件配置解析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之web服务器shttpd源码剖析——命令行解析&#xff0c;在这篇文章中&#xff0c;你将会学习到在Linux内核中如何创建一个自己的并发服务器shttpd&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘…

单链表的应用

文章目录 目录1. 单链表经典算法OJ题目1.1 [移除链表元素](https://leetcode.cn/problems/remove-linked-list-elements/description/)1.2 [链表的中间节点](https://leetcode.cn/problems/middle-of-the-linked-list/description/)1.3 [反转链表](https://leetcode.cn/problem…

CTFHUB-技能树-Web前置技能-文件上传(无验证,JS前端验证,前端验证)

CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09; 文章目录 CTFHUB-技能树-Web前置技能-文件上传&#xff08;无验证&#xff0c;JS前端验证&#xff0c;前端验证—.htaccess&#xff09;文件上传无验…

GPT-3.5和GPT-Plus的区别

GPT-3.5和GPT-Plus都是OpenAI开发的大型语言模型,但它们之间有一些区别: GPT-3.5就是大家熟知的ChatGPT GPT-Plus 是Open AI 的更强的AI模型GPT-4版本。两者区别是&#xff1a; 模型规模:GPT-Plus是GPT-3的一个更大版本,参数量更多。而GPT-3.5是GPT-3的一个优化版本,在参数量…

✌粤嵌—2024/3/11—跳跃游戏

代码实现&#xff1a; 方法一&#xff1a;递归记忆化 int path; int used[10000];bool dfs(int *nums, int numsSize) {if (path numsSize - 1) {return true;}for (int i 1; i < nums[path]; i) {if (used[path i]) {continue;}path i;used[path] 1;if (dfs(nums, num…

双指针的引入和深入思考(持续更新中)

目录 1.引入双指针 2.使用场景 3.例题引入 1.引入双指针 当我们需要维护某个区间性质的或者是求满足某些性质的区间的长度时&#xff0c;对于一个区间是由左右端点的&#xff0c;我们有简单的枚举左右端点的O()的时间的做法&#xff0c;当时在大多数题目中是不可行的&#…

百度OCR身份证识别C++离线SDKV3.0 C#对接

百度OCR身份证识别C离线SDKV3.0 C#对接 目录 说明 效果 问题 项目 代码 下载 说明 自己根据SDK封装了动态库&#xff0c;然后C#调用。 SDK 简介 本 SDK 适应于于 Windows 平台下的⾝份证识别系统,⽀持 C接⼜开发的 SDK,开发者可在VS2015 下⾯进⾏开发&#xff08;推荐…