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

92.【C语言】数据结构之单向链表的查找,中间插入和删除,销毁

目录

1.链表的查找函数

2.链表的修改函数

3.链表的中间插入函数

1.在pos之前插入:SLTInsertBefore函数

1.借助头指针pphead

示意图

代码示例(写入SList.c)

头文件添加SLTInsertbefore的声明

main.c的部分代码改为

1.测试中间插入

2.测试头部插入

3.测试pos为NULL的情况

2.不借助头指针pphead

代码示例

2.在pos之后插入:SLTInsertAfter函数

代码示例

错误写法

4.链表的中间删除函数

示意图(非头删)

1.在pos之前删除:SLTEraseBefore函数

1.借助头指针pphead

代码示例

头文件添加SLTErase的声明

main.c的部分代码改为

运行结果

2.不借助头指针pphead

示意图

代码示例

2.在pos之后删除:SLTEraseBeforeAfter函数

代码示例

4.链表的销毁函数

代码示例(写入SList.c)

main.c部分代码改为

运行结果

错误写法

VS2022+debug+x86环境下调试错误代码


承接91.【C语言】数据结构之链表的头删和尾删文章

这里均以单向链表做演示

1.链表的查找函数

代码示例(遍历查找)

void SLTFind(SLTNode* phead, SLTDataType find)
{SLTNode* cur = phead;//初始化cur指针while (cur){if (cur->data == find){return cur;}//找不到则将下一个节点的地址赋值给curcur = cur->next;}//从头找到尾没找到,则返回NULLreturn NULL;
}

2.链表的修改函数

有了查找函数,就可以轻松实现修改函数

修改函数的策略:先查某个节点的数据,再对这个数据进行修改

代码示例(写入SList.c)

void SLTMod(SLTNode* phead, SLTDataType find, SLTDataType mod)
{//将需要修改数据的节点的地址赋值给tar_p//tar_p为目标指针(target_pointer)SLTNode* tar_p = SLTFind(phead, find);//修改目标节点的数据tar_p->data = mod;
}

main.c部分代码改为

void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTFind(plist, 3);SLTMod(plist, 3, 5);SLTPrint(plist);
}

执行结果

3.链表的中间插入函数

插入包括:在pos之前插入和在pos之后插入

1.在pos之前插入:SLTInsertBefore函数

1.借助头指针pphead

示意图

在pos之前插入,要找pos前的节点,需要参数SLTNode* phead

代码示例(写入SList.c)
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos,SLTDataType x)
{//判断pos是否为NULLassert(pos);//pphead不能为NULLassert(pphead);//判断pos是否为头指针,如果是则调用现有的函数if (pos == *pphead){SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//初始化新节点SLTNode* newnode = BuySLTNode(x);prev->next = newnode;newnode->next = pos;}
}

注意:

1.一开始就要判断判断pos是否为NULL

2.将pos分是否为头指针两种情况讨论

如果不判断pos是否为头指针,直接硬插入的话,会报错

分析原因:当pos为头指针时,pos和prev指针存储的内容是一样的,第一次循环条件prev->next!=pos成立,错过了prev->next==pos的机会,则while会一直循环,直到prev为NULL(x86下存储的00 00 00 00),出现NULL->next是不合法的,因此报错

3.pphead不能为NULL(即plist存储的地址不能为NULL),plist可以为NULL(空链表)

头文件添加SLTInsertbefore的声明
main.c的部分代码改为
1.测试中间插入
void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTNode* pos = SLTFind(plist, 3);SLTInsertBefore(&plist, pos, 5);SLTPrint(plist);
}

2.测试头部插入
SLTNode* pos = SLTFind(plist, 1);

 

3.测试pos为NULL的情况

均可以实现

2.不借助头指针pphead

只需要交换即可

代码示例
void SLTInsertBefore(SLTNode** pos, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);//用中间变量n_tmp(全称next_tmp)交换SLTDataType tmp = (*pos)->data;(*pos)->data = newnode->data;newnode->data = tmp;//找pos的下一个节点,暂存到n_tmpSLTNode* n_tmp = (*pos)->next;//变动指针(*pos)->next = newnode;newnode->next = n_tmp;
}

 头插和尾插均可

2.在pos之后插入:SLTInsertAfter函数

代码示例
void SLTInsertAfter(SLTNode* pos,SLTDataType x)
{assert(pos);//pos不可为NULLSLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;
}

错误写法

void SLTInsertAfter(SLTNode* pos,SLTDataType x)
{assert(pos);//pos不可为NULLSLTNode* newnode = BuySLTNode(x);pos->next = newnode;newnode->next = pos->next;
}

反过来写会出问题,比如想在d2节点后插入新节点

这样做是无效

4.链表的中间删除函数

示意图(非头删)

1.在pos之前删除:SLTEraseBefore函数

1.借助头指针pphead

代码示例
void  SLTEraseBefore(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);assert(*pphead);if (*pphead == pos){SLTPopFront(pphead);}else{//找pos的前一个SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);}
}

注意:

1.断言pphead,*pphead(即plist)和pos

2.头删直接调用SLTPopFront函数

3.不采取pos = NULL;,SLTErase中的pos为形参,没有办法真正为删除的节点含有的指针置NULL,应该在main.c中操作

头文件添加SLTErase的声明
main.c的部分代码改为
void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTNode* pos = SLTFind(plist, 3);SLTEraseBefore(&plist,pos);pos = NULL;SLTPrint(plist);
}

注意pos = NULL;

运行结果

2.不借助头指针pphead

示意图

代码示例
void  SLTEraseBefore(SLTNode** pos)
{assert((*pos)->next);(*pos)->data = ((*pos)->next)->data;(*pos)->next = ((*pos)->next)->next;
}
//或写成下面这样
void  SLTEraseBefore(SLTNode* pos)
{assert(pos->next);pos->data = (pos->next)->data;pos->next = (pos->next)->next;
}

注意:此方法有缺陷,不能尾删,因此断言

2.在pos之后删除:SLTEraseBeforeAfter函数

代码示例
void SLTEraseAfter(SLTNode* pos)
{assert(pos);//不为空链表assert(pos->next);//不为末尾节点SLTNode* delete = pos->next;//也可以写成pos->next = delete->next;pos->next = (pos->next)->next;free(delete);delete = NULL;
}

注意:不可以不写SLTNode* delete = pos->next;,一旦pos->next被修改后,要删除的节点的指针会丢失,因此要先用结构体指针delete保存

4.链表的销毁函数

代码示例(写入SList.c)

采用双指针法

void SLTDestory(SLTNode* phead)
{SLTNode* p1 = phead;while (p1){SLTNode* p2 = p1->next;free(p1);p1 = p2;}
}

注:

1.p1相当于慢指针,p2相当于快指针

2.一定先保存p1->next才能free(p1);防止p1->next值被操作系统修改从而找不到下一个节点的地址!

main.c部分代码改为

void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTDestory(plist);plist = NULL;//不能在SLTDestory内置NULL,形参的改变不影响实参
}

注:如果不想在main.c中手动为plist置空,可以修改SLTDestory(&plist);

void SLTDestory(SLTNode** pphead)
{assert(pphead);SLTNode* p1 = *pphead;while (p1){SLTNode* p2 = p1->next;free(p1);p1 = p2;}*pphead = NULL;
}

运行结果

错误写法

void SLTDestory(SLTNode* phead)
{SLTNode* p1 = phead;while (p1){SLTNode* p2 = p1;free(p1);p1 = p2->next;}
}

对free的本质认识不清楚,free函数是将指针所指向的内存空间的使用权交还给操作系统,操作系统会改变内存空间的值,并没有改变指针的值,因此p2->next会变成野指针

VS2022+debug+x86环境下调试错误代码

SLTNode* p2 = p1;执行后

free(p1);执行后

p1->next被操作系统修改成0xdddddddd,p1->next为野指针

第二次执行完SLTNode* p2 = p1;后

显然再次执行free(p1);肯定会报错,访问冲突,无权限修改内存

相关文章:

92.【C语言】数据结构之单向链表的查找,中间插入和删除,销毁

目录 1.链表的查找函数 2.链表的修改函数 3.链表的中间插入函数 1.在pos之前插入:SLTInsertBefore函数 1.借助头指针pphead 示意图 代码示例(写入SList.c) 头文件添加SLTInsertbefore的声明 main.c的部分代码改为 1.测试中间插入 2.测试头部插入 3.测试pos为NULL的…...

WPF+MVVM案例实战(七)- 系统初始化界面字体描边效果实现

文章目录 1、案例效果展示2、项目准备3、功能实现1、资源获取2、界面代码3、后台代码4 源代码获取1、案例效果展示 2、项目准备 打开项目 Wpf_Examples,新建系统初始化界面 WelcomeWindow.xmal,如下所示: 3、功能实现 1、资源获取 案例中使用的CSDN文字为路径文字,从字体…...

基于 C# 的 AI 算法测试方法

基于 C# 的 AI 算法测试方法 在当今人工智能蓬勃发展的时代,AI 算法的质量和可靠性至关重要。对于使用 C# 开发的 AI 算法,我们需要一套有效的测试方法来确保其性能、准确性和稳定性。本文将详细探讨基于 C# 的 AI 算法测试方法,帮助开发者更…...

Find My画框|苹果Find My技术与画框结合,智能防丢,全球定位

画框通常用于保护和固定艺术品,尤其是绘画作品。它是一种可以展示艺术品的框架,用于保护艺术品免受损坏或污染。艺术品被放置在画框内,可以避免受到空气、尘土和其他外部因素的损害。同时,画框还可以增强艺术品的展示效果&#xf…...

布谷语音源码服务器搭建环境及配置流程

布谷语音源码部署环境安装要求(只有在相同的环境下才更容易避免一些不必要的麻烦):●安装Center OS 7.9,我们自己的服务器使用的是7.9建议相同系统,非强制●安装宝塔环境(强烈推荐使用)●安装软…...

算法|牛客网华为机试21-30C++

牛客网华为机试 上篇:算法|牛客网华为机试10-20C 文章目录 HJ21 简单密码HJ22 汽水瓶HJ23 删除字符串中出现次数最少的字符HJ24 合唱队HJ25 数据分类处理HJ26 字符串排序HJ27 查找兄弟单词HJ28 素数伴侣HJ29 字符串加解密HJ30 字符串合并处理 HJ21 简单密码 题目描…...

Tomcat servlet response关于中文乱码的经验

前言 最近修改老项目项目,使用zuul网关返回的中文内容乱码了,如果使用GBK或者GB2312编码确正常显示,稍微实验了一下,发现里面很多细节,毕竟Springboot对我们做了很多事情,而且当我们使用不同的模式会出现很…...

WebGIS开发丨从入门到进阶,全系列课程分享

WebGIS开发所需的技能 1.前端技能:Html、CSS、 Javascript、WebAPLs、Vue 2.二维技能:WebGIS基础理论及开发、MapGIS二次开发Openlayers、Leaflet、Mapbox 、Echarts、公共开发平台开发等 3.三维技能:Blender、Three.js、Cesium等 Web开发…...

C++ 模板专题 - 标签分派(Tag Dispatching)

一:概述: 在 C 中,Tag Dispatching 是一种编程技巧,主要用于在编译期根据不同的类型或特征选择不同的函数重载或代码分支。Tag Dispatching 借助类型标签(tags)进行函数调度,用于在模板中实现编译期的静态分…...

如何解决RabbitMQ消息的重复消费问题

什么情况下会导致消息的重复消费——在消费者还没成功发送自动确认机制时发生: 网络抖动消费者挂了 解决方案 每条消息设置一个唯一的标识id幂等方案:【Redis分布式锁、数据库锁(悲观锁、乐观锁)】 面试官:如何解决…...

Java调用chatgpt

目前openai的chatgpt在国内使用有一定难度,不过国内的大模型在大部分情况下已经不弱于chatgpt,而且还更便宜,又能解决国内最敏感的内容安全问题。本文后续以spring ai调用国内chatgpt厂商实现为例,讲解怎么构建一个java调用chatgp…...

将你的 Kibana Dev Console 请求导出到 Python 和 JavaScript 代码

作者:来自 Elastic Miguel Grinberg Kibana Dev Console 现在提供将请求导出到可立即集成到你的应用程序中的 Python 和 JavaScript 代码的选项。 你使用过 Kibana 开发控制台吗?这是一个非常棒的原型设计工具,可让你以交互方式构建和测试 El…...

成都世运会志愿者招募报名流程及证件照制作方法

成都世运会志愿者招募正在如火如荼地进行中,许多热心公益的青年们纷纷报名参与。本文将详细介绍如何通过官方渠道报名,并使用手机来自行制作符合要求的4:5比例的白底证件照。 一、志愿者报名流程概述首先,报名成都世运会志愿者需要通过官方指…...

大数据技术的前景如何?

在当今数字化迅猛发展的时代,大数据技术的前景显得尤为广阔。随着数据量的激增,如何有效利用这些数据成为了各行各业关注的焦点。未来五年,大数据技术的发展趋势可以从市场规模、技术融合、行业应用和政策支持等多个方面进行深入分析。 1. 市…...

LLM | 论文精读 | 基于大型语言模型的自主代理综述

论文标题:A Survey on Large Language Model based Autonomous Agents 作者:Lei Wang, Chen Ma, Xueyang Feng, 等 期刊:Frontiers of Computer Science, 2024 DOI:10.1007/s11704-024-40231-1 一、引言 自主代理(…...

详解Redis相关缓存问题

目录 缓存更新策略 定期⽣成 实时⽣成 缓存淘汰策略 Redis内置缓存淘汰策略 缓存预热 缓存穿透 缓存雪崩 缓存击穿 缓存更新策略 定期⽣成 每隔⼀定的周期(⽐如⼀天/⼀周/⼀个⽉), 对于访问的数据频次进⾏统计. 挑选出访问频次最⾼的前 %N的数据. 实时⽣成 先给缓存…...

ubuntu 24 (wayland)如何实现无显示器远程桌面

ubuntu 24默认采用的是wayland而非x11,查过文档vnc对wayland的支持不是很好,折腾了好久,弄了一个如下的方案供参考: 硬件条件 需要一个显卡欺骗器或者可以接HDMI口作为视频信号源输出的设备。 将ubuntu的主机的HDMI输出接到该硬…...

《模拟电子技术基础》第六版PDF课后题答案详解

《模拟电子技术基础》第六版是在获首届全国优秀教材建设奖一等奖的第五版的基础上,总结6年来的教学实践经验修订而成的新形态教材。为满足国家人才培养的需求,适应新型教学模式,并考虑到大多数院校逐渐减少课程学时的现状,在不降低…...

python知识收集

文章目录 语法def声明函数class声明类class 子类(父类) 继承 数据结构列表列表操作 元组元组操作 字典遍历字典 集合 文件读写读文件写文件 csv模块读入写入 time模块发送邮件制作二维码滚动广告 语法 def声明函数 class声明类 class 子类(父类) 继承 数据结构 列表 列表…...

传奇996_3——使用补丁添加怪物

找素材,看素材是否是打包好的,没有的话就使用工具进行素材打包(打包好后尽量别改名),并复制进客户端,D:\chuanqinew\996M2_debug\dev\anim\monster找到模型表cfg_model_info.xls,复制表中前几行…...

「Mac畅玩鸿蒙与硬件13」鸿蒙UI组件篇3 - TextInput 组件获取用户输入

在鸿蒙应用开发中,TextInput 组件用于接收用户输入,适用于文本、密码等多种输入类型。本文详细介绍鸿蒙 TextInput 组件的使用方法,包括输入限制、样式设置、事件监听及搜索框应用,帮助你灵活处理鸿蒙应用中的用户输入。 关键词 TextInput 组件用户输入输入限制事件监听搜索…...

MCU裸机任务调度架构

第1章 方式一(平均主义) int main(int argc, char **argv){/* RTC 初始化 */bsp_RTC_Init(&rtc);/* 串口初始化 */uartInit(115200);/* LED初始化 */ledInit();while(1){// 任务1(获取传感器数据)// 任务2// 任务3} } 1.1 平均主义的缺陷 获取传感器数据可以600ms去读取一…...

【Web前端】JavaScript 对象原型与继承机制

JavaScript 是一种动态类型的编程语言,其核心特性之一就是对象和原型链。理解原型及其工作机制对于掌握 JavaScript 的继承和对象关系非常重要。 什么是原型 每个对象都有一个内部属性 ​​[[Prototype]]​​​,这个属性指向创建该对象的构造函数的原型…...

【华为HCIP实战课程二十六】中间到中间系统协议IS-IS配置默认路由及IS-IS数据库,网络工程师

一、IS-IS路由器分类 1、L1路由器:Level-1路由器负责区域内的路由,它只与属于同一区域的Level-1和Level-1-2路由器形成邻居关系,属于不同区域的Level-1路由器不能形成邻居关系。Level-1路由器只负责维护Level-1的链路状态数据库LSDB,该LSDB包含本区域的路由信息。到本区域…...

mysql上课总结(2)(DCL的所有操作总结、命令行快速启动/关闭mysql服务)

目录 一、DCL小结(数据控制语言) 1、查询表不在当前使用的数据库,可以在表名前加数据库名。 2、系统数据库mysql 的 user 表。 3、在系统数据库mysql 的 user 表当中如何判断创建的用户是否唯一? 4、系统数据库mysql 的 user 表当…...

法律智能助手:开源NLP系统助力法律文件高效审查与检索

一、系统概述 思通数科AI平台是一款融合了自然语言处理和多标签分类技术的开源智能文档分类工具,特别适用于法律行业。平台采用深度学习的BERT模型来进行特征提取与关系抽取,实现了精准的文档分类和检索。用户可以在线训练和标注数据,使系统…...

如何使用AdsPower指纹浏览器克服爬虫技术限制,安全高效进行爬虫!

随着中国开发者日益成熟,应用质量明显提升,越来越多的开发者选择出海寻找机会扩大市场。但“应用出海”说起来容易,做起来难。其中,最大的困恼就是对海外市场缺乏了解。 很多开发者会选择使用网络爬虫(Web Crawling&a…...

四、虚拟化配置寄存器(HCR_EL2)

bit字段描述63:60TWEDELTWE延迟。当HCR_EL2.TWEDEn为1,由HCR_EL2引起的WFE*陷阱的最小延迟为2的(TWEDEL 8)次方,单位周期。59TWEDEnTWE推迟启用。让由HCR EL2.TWE引起的WFE*指令延迟陷入可配置。0:陷入的延迟是已经定义的;1&…...

我要成为算法高手-滑动窗口篇

目录 滑动窗口算法题目1:长度最小的子数组题目2:无重复字符的最长子串题目3:最大连续1的个数题目4:将x减到0的最小操作数题目5:水果成篮题目6:找到字符串中所有的字母异位词题目7:串联所有单词的子串题目8:最小覆盖子串 滑动窗口算法 滑动窗口的本质还是双指针,只不…...

jenkins搭建及流水线配置

1.安装docker curl https://mirrors.aliyun.com/repo/Centos-7.repo >> CentOS-Base-Aliyun.repomv CentOS-Base-Aliyun.repo /etc/yum.repos.d/yum -y install yum-utils device-mapper-persistent-data lvm2yum-config-manager --add-repo http://mirrors.aliyun.com/…...

网站正在建设中页面/it培训机构培训费用

高阶反函数的导数 {xu(t)yv(t)\begin{cases} xu(t)& \text{}\\ yv(t)& \text{} \end{cases} {xu(t)yv(t)​​ 则y′dydxdv(t)du(t),结果为t的函数f(t)则y\frac{dy}{dx}\frac{dv(t)}{du(t)},结果为t的函数f(t)则y′dxdy​du(t)dv(t)​,结果为t的函数f(t) y′′dy′dxddv…...

图片站手机网站怎么做/公司营销网站建设

导读:国内手机网站目前还算是个新鲜事物,相应的手机网站前端开发也并不是特别成熟,对于一个网页设计师来说要做一个手机网站还是会碰到许多问题,本文转载自淘宝 UED,分享如何开发进行手机网站的前端卡发。 从09年初接手…...

网站公安备案需要几个工作日/所有的竞价托管公司

我们很多人都听说过Socket编程也称网络编程,在我们当今的社会中网络已经深入到我们的生活中了,计算机的网络通信也成为我们生活中必不可少的一部分。而实现我们网络通信就得依靠网络编程,让我们的计算机之间可以互相通信。 本篇文章主要是针对…...

云南企业建站/网络舆情分析报告范文

安装 配置 1. 登陆 publisher 实例,点击复制— > 本地发布— > 新建发布 2. 新建发布向导,下一步即可 3. 选择使用本机作为发布服务器 4. 选择发布数据库 5. 选择发布类型,本处为事务性发布 6. 选择发布对象 7. 选择筛选表行&#xff0…...

一流的聊城做网站公司/推广平台怎么做

一、整篇文章在讲什么?归纳法是通过一般推出规律的一种逻辑思维方法,归纳法是一种重要的思维方式。二、每个章节讲什么? 1、人的智商是未经打磨的钻石,逻辑训练就是打磨、切割这颗钻胚,让其最终成为一枚锋利无比、璀璨…...

wordpress会员可见/b2b推广网站

php生成二维码其实挺简单的;当然指的是使用qrcode类库; 因此关于是否要写这篇博客;我是犹豫了再三的; 不过最后还是决定写下吧;如果有童鞋急着用;就可以直接引了; 再个也可以作为即将写的文章微…...