当前位置: 首页 > news >正文

【C语言】实现单链表


目录

(一)头文件

(二)功能实现

(1)打印单链表

(2)头插与头删 

 (3)尾插与尾删

(4) 删除指定位置节点 和 删除指定位置之后的节点

 (5)指定位置之前插入节点 和 指定位置之后插入节点

(6)销毁链表


正文开始:

(一)头文件

         命名为 "LST.h"

        这里不加解释的给出单链表的头文件,并根据头文件来实现单链表的基本功能:

        包括打印单链表,头插与头删,尾插与尾删,删除指定位置的节点,删除指定位置之后的节点,指定位置之前插入节点,指定位置之后插入节点,销毁链表等十个功能。

#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//链表的数据类型
typedef int SLTDatatype;//链表的一个节点
typedef struct SLTNode
{SLTDatatype data;struct SLTNode* next;
}SLTNode;//print SLT
void slPrint(SLTNode* phead);//buy_new_new
SLTNode* Get_Newnode(SLTDatatype x);//head_push
void slHeadpush(SLTNode** pphead, SLTDatatype x);//head_del
void slHeaddel(SLTNode** pphead);//tail_push
void slTailpush(SLTNode** pphead,SLTDatatype x);//tail_del
void slTaildel(SLTNode** pphead);//查找数据
SLTNode* sl_find(SLTNode** pphead, SLTDatatype x);/**** FUN 删除指定位置之后的节点* 参数 pos表示data==这个数据的节点* 返回值 无
****/
void SLTEraseAfter(SLTNode* pos);/**** Fun 删除指定位置的节点* 参数 pos* 返回值 无
****/
void slDelPos(SLTNode** pphead, SLTNode* pos);/**** Fun 指定位置之前插入节点* 参数 pos* 返回值 无
****/
void slInsertpos(SLTNode** pphead, SLTNode* pos, SLTDatatype x);//在指定位置之后插入数据
void slInsertAfter(SLTNode* pos, SLTDatatype x);//销毁链表
void sl_destory(SLTNode**pphead);

(二)功能实现

         创建链表(以及初始化):

	SLTNode* pl = NULL;    //链表存储的是空指针,此时表示链表为空

(1)打印单链表

        打印链表并不需要改变链表本身,因此只需要传值(传值意味着形参与实参没有联系)调用;

        通常我们在遍历链表时,总会创建一个pcur指针表示当前指向的节点,这样不会因为遍历而丢失重要指针的值;


//print SLT
void slPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d-->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}

(2)头插与头删 

         在执行插入(包括头插,尾插,特定位置插入)操作时,总会重复使用一个功能:获取新节点,所以我们将获取新节点封装为一个函数:

Get_Newnode():


//buy_new_node
SLTNode* Get_Newnode(SLTDatatype x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}

头插与头删

头插

        首先传递的指针不为空,通过assert断言来判断;

        申请新节点,并将新节点放在链表的头部;

//head_push
void slHeadpush(SLTNode** pphead, SLTDatatype x)
{//指针不为空assert(pphead);//申请新节点SLTNode* newnode = Get_Newnode(x);//转变头节点newnode->next = *pphead;*pphead = newnode;
}

头删

        首先传递的指针不为空,链表也不为空(如果为空,那么无法执行头删),通过assert断言来判断;

        如果直接将头free掉,就无法对链表的原头解引用(->也是解引用的一种)那么链表的新头就无法找到了。所以创建一个del指针,暂时保存链表的原头(也是将要释放的节点),当链表的头指针后移找到新头后,再通过del释放原头。


//head_del
void slHeaddel(SLTNode** pphead)
{//指针不为空assert(pphead);//链表不为空assert(*pphead);SLTNode* del = *pphead;*pphead = (*pphead)->next;free(del);del = NULL;
}

 (3)尾插与尾删

尾插

         首先传递的指针不为空,通过assert断言来判断;

        尾插通常是在尾部插入,但是如果链表为空,尾插就变成了头插;

        如果链表为空,新节点作为头节点;链表不为空,找到尾节点,进行尾插;

//tail_push
void slTailpush(SLTNode** pphead, SLTDatatype x)
{assert(pphead);SLTNode* newnode = Get_Newnode(x);//链表为空,新节点作为头节点if (*pphead == NULL){*pphead = newnode;return;}SLTNode* pcur = *pphead;//链表不为空,找到尾节点while (pcur->next){pcur = pcur->next;}pcur->next = newnode;
}

尾删

        首先传递的指针不为空,链表也不为空(如果为空,那么无法执行尾删),通过assert断言来判断;

        尾删通常是删除尾部的节点,如果只有一个节点,尾删就变成了头删;

        如果只有一个节点,直接删除;如果有多个节点,现找尾,再执行尾删;


//tail_del
void slTaildel(SLTNode** pphead)
{assert(pphead);assert(*pphead);//链表不为空//只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}//有多个节点SLTNode* prev = NULL;SLTNode* ptail = *pphead;//找尾while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;//销毁尾节点free(ptail);ptail = NULL;
}

(4) 删除指定位置节点 和 删除指定位置之后的节点

        指定位置指定的是某一个存在于链表中的数据的位置,这意味着我们先要找到这个已经存在的数据,封装一个函数:

        sl_find():

//查找数据
SLTNode* sl_find(SLTNode** pphead, SLTDatatype x)
{SLTNode* pcur = *pphead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}

删除指定位置之后的数据

        相比于删除指定位置,删除指定位置之后更简单;

        因为删除指定位置之后仅需要指定位置的节点,不需要遍历查找;删除指定位置需要知道指定位置之前的节点,需要遍历查找;

删除指定位置之后

        首先传递的指针不为空,这个位置也不能是尾节点(尾节点后面没有可以删除的节点),通过assert断言来判断;

        如果直接将节点free掉(设指定位置为P节点),就无法对P节点解引用(->也是解引用的一种)那么链表P节点后的就无法找到了。所以创建一个del指针,暂时保存链表的P节点后的指针,当P前与P后相连后,再通过del释放P节点。


/**** FUN 删除指定位置之后的节点* 参数 pos表示data==这个数据的节点* 返回值 无
****/
void SLTEraseAfter(SLTNode* pos)
{assert(pos);//pos->next不能为空assert(pos->next);//pos  pos->next  pos->next->nextSLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}

删除指定位置

        首先传递的指针不为空,链表也不为空(如果为空,那么无法执行删除),通过assert断言来判断;

        如果pos 刚好是头节点,直接删除;

        pos不是头节点,找到pos,再执行删除;先创建一个prev节点,遍历链表,指向P节点之前;


/**** Fun 删除指定位置的节点* 参数 pos* 返回值 无
****/
void slDelPos(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);assert(pos);//pos 刚好是头节点,直接删除if (*pphead == pos){slHeaddel(pphead);return;}//pos不是头节点,找到posSLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//链接prev->next = pos->next;free(pos);pos = NULL;
}

 (5)指定位置之前插入节点 和 指定位置之后插入节点

         指定位置之前插入节点 与 指定位置之前删除节点类似,都需要创建prev指针,遍历链表;

指定位置之前插入节点 

        首先传递的指针不为空,链表也不为空(如果pos不为空,所以链表一定不为空,【因为链表为空是pos为空的充分条件】两者是逆否命题),通过assert断言来判断;

         如果pos是头节点,则头插;pos不是头节点,则找到pos,通过prev插入新节点;


/**** Fun 指定位置之前插入节点* 参数 pos* 返回值 无
****/
void slInsertpos(SLTNode** pphead, SLTNode* pos,SLTDatatype x)
{assert(pphead);assert(pos);//要加上链表不能为空assert(*pphead);SLTNode* newnode = Get_Newnode(x);//pos是头节点if (*pphead == pos){slHeadpush(pphead, x);return;}//pos不是头节点SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;
}

指定位置之后插入节点

        直接插入即可;


//在指定位置之后插入数据
void slInsertAfter(SLTNode* pos, SLTDatatype x)
{assert(pos);SLTNode* newnode = Get_Newnode(x);newnode->next = pos->next;pos->next = newnode;
}

(6)销毁链表

       首先传递的指针不为空,通过assert断言来判断;

        通过循环一个接着一个释放,在每次释放之前,创建一个next指针保存下一个节点,防释放后无法通过解引用找到下一个节点;

        最后,将链表置空;


//销毁链表
void sl_destory(SLTNode**pphead)
{assert(pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

完~

未经作者同意禁止转载 

相关文章:

【C语言】实现单链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09;功能实现 &#xff08;1&#xff09;打印单链表 &#xff08;2&#xff09;头插与头删 &#xff08;3&#xff09;尾插与尾删 &#xff08;4&#xff09; 删除指定位置节点 和 删除指定位置之后的节点 …...

Hive调优——合并小文件

目录 一、小文件产生的原因 二、小文件的危害 三、小文件的解决方案 3.1 小文件的预防 3.1.1 减少Map数量 3.1.2 减少Reduce的数量 3.2 已存在的小文件合并 3.2.1 方式一&#xff1a;insert overwrite (推荐) 3.2.2 方式二&#xff1a;concatenate 3.2.3 方式三&#xff…...

设计模式(行为型模式)责任链模式

目录 一、简介二、责任链模式2.1、处理器接口2.2、具体处理器类2.3、使用 三、优点与缺点 一、简介 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;允许你将请求沿着处理者链进行传递&#xff0c;直到有一个处理者能够处理…...

HTTP和HTTPS区别!

http 是我们几乎天天都要打交道的东西&#xff0c;相关知识点有点多&#xff0c;所以也有不少面试必问的点&#xff0c;这里做了一些整理&#xff0c;帮且大家树立完整的 http 知识体系&#xff0c;对面试官说 so easy HTTP 的特点和缺点 特点&#xff1a;无连接、无状态、灵…...

麻将普通胡牌算法(带混)

最近在玩腾讯的麻将游戏,但是经常需要充值,于是就想自己实现一个简单的单机麻将游戏.第一个难点就是实现胡牌的判断.这里写一下心得. 术语 本文的胡牌是指手牌构成了3N2的牌型,即一对做将,剩下的牌均为刻子(3张一样的牌)或者顺子(3张连续的牌比如234饼). 下面就是一个14张牌…...

Rust结构体详解:定义、使用及方法

Rust 是一门强调安全性和性能的系统级编程语言&#xff0c;它引入了结构体&#xff08;struct&#xff09;作为一种自定义的数据类型&#xff0c;允许程序员以更加灵活的方式组织和操作数据。在本篇博客中&#xff0c;我们将深入探讨 Rust 结构体的定义、使用以及相关概念。 什…...

LeetCode、435. 无重叠区间【中等,贪心 区间问题】

文章目录 前言LeetCode、435. 无重叠区间【中等&#xff0c;贪心 区间问题】题目链接及分类思路贪心、区间问题 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技…...

【实战】一、Jest 前端自动化测试框架基础入门(三) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(三)

文章目录 一、Jest 前端自动化测试框架基础入门7.异步代码的测试方法8.Jest 中的钩子函数9.钩子函数的作用域 学习内容来源&#xff1a;Jest入门到TDD/BDD双实战_前端要学的测试课 相对原教程&#xff0c;我在学习开始时&#xff08;2023.08&#xff09;采用的是当前最新版本&a…...

信息学奥赛一本通1228:书架

1228&#xff1a;书架 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 18190 通过数: 10557 【题目描述】 John最近买了一个书架用来存放奶牛养殖书籍&#xff0c;但书架很快被存满了&#xff0c;只剩最顶层有空余。 John共有N&#xfffd;头奶牛(1≤N≤20,0001≤…...

红队打靶练习:GLASGOW SMILE: 1.1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 1、gobuster 2、dirsearch WEB web信息收集 /how_to.txt /joomla CMS利用 1、爆破后台 2、登录 3、反弹shell 提权 系统信息收集 rob用户登录 abner用户 penguin用户 get root flag 信息收集…...

网络安全的今年:量子、生成人工智能以及 LLM 和密码

尽管世界总是难以预测&#xff0c;但网络安全的几个强劲趋势表明未来几个月的发展充满希望和令人担忧。有一点是肯定的&#xff1a;2024 年将是非常重要且有趣的一年。 近年来&#xff0c;人工智能&#xff08;AI&#xff09;以令人难以置信的速度发展&#xff0c;其在网络安全…...

【FPGA】Verilog:奇偶校验位发生器 | 奇偶校验位校验器

目录 0x00 奇偶校验位发生器 0x01 奇偶校验位校验器 0x02 错误检测器和纠错器...

【心得】关于STM32中RTC的校准方法

最近看了一些关于RTC校准的帖子&#xff0c;发现很多人存在疑惑。正好最近我也在STM32中实现了RTC校准。发些心得。这些对老手来说有些罗索&#xff0c;但对新手有益处。 实现RTC 校准的核心之一是库文件Stm321f0x_bkp.c中的void BKP_SetRTCCalibrationValue (uint8_t Calibra…...

消息中间件面试篇

目录 消息中间件 RabbitMQ 消息不丢失 生产者确认机制 消息持久化 交换机持久化 队列持久化 消息持久化 消费者确认 消息重复消费 出现的场景 解决方案 每条消息设置一个唯一的标识id 幂等方案&#xff1a;【 分布式锁、数据库锁&#xff08;悲观锁、乐观锁&#…...

【MySQL】-20 MySQL综合-6(MySQL创建数据表+MySQL修改数据表+MySQL删除数据表)

MySQL创建数据表MySQL修改数据表MySQL删除数据表 MySQL创建数据表基本语法在指定的数据库中创建表查看表结构 MySQL修改数据表基本语法添加字段修改字段数据类型删除字段修改字段名称修改表名 MySQL删除数据表基本语法删除表 MySQL创建数据表 在创建数据库之后&#xff0c;接下…...

linux查看当前连接的IP

linux下查询当前所有连接的ip_linux查看某个ip的连接-CSDN博客 netstat -ntu | grep tcp | awk {print $5} | cut -d: -f1 | sort | uniq -c | sort -nr...

洛谷_P1923 【深基9.例4】求第 k 小的数_python写法

哪位大佬可以出一下这个的题解&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;话说蓝桥杯可以用numpy库吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 这道题有一个很简单的思路就是排序完成之后再访问。 but有很大的问题&…...

【MySQL】学习约束和使用图形化界面创建表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iqtbME2KmWpQFQSt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…...

QGIS编译(跨平台编译)之四十八:pixman编译(Windows、Linux、MacOS环境下编译)

文章目录 一、pixman介绍二、pixman下载三、Linux下编译四、MacOS下编译五、Windows下编译一、pixman介绍 Pixman 是一个开源的图形库,它提供了底层像素操作功能,包括像素格式转换、图像合成、图像缩放、图像旋转等多种操作。Pixman 主要被用作 Cairo 图形库的后端,支持 Ca…...

华为数通方向HCIP-DataCom H12-821题库(单选题:441-460)

第441题 下面是一台路由输出的信息,关于这段信息描述正确的是 <R1>display bgp peerBGP local router ID : 2.2.2.2Local AS number : 100Total number of peers : 2 Peers in established state : 0Peer V AS MsgRcvd MsgSent OutQ Up/Down …...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...