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

数据结构入门(3)2.链表接口实现

目录

前言

头文件

动态申请一个结点

单链表打印 

单链表尾插 

单链表的头插

单链表的尾删

单链表头删

单链表查找

单链表在pos位置之后插入x

单链表删除pos位置之后的值

在pos的前面插入

删除pos位置

销毁顺序表


前言

本文将介绍链表常见的功能的实现

头文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDateType;
typedef struct SListNode
{SLTDateType val;struct SListNode* next;
}SListNode;// 动态申请一个结点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode* pos);
// 在pos的前面插入
void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
// 删除pos位置
void SLTErase(SListNode** pphead, SListNode* pos);
//销毁顺序表
void SLTDestroy(SListNode** pphead);

动态申请一个结点

原理:链表的结点所代表的是一个内存块,里面包含着该节点的值以及指向下一个结点地址的指针,用动态申请的方式更加方便,插入时只需要将前一个结点里的指针指向自己即可,但新结点刚创建时,里面的指针指向空,不要变为野指针。

SListNode* BuySListNode(SLTDateType x)
{SListNode* ans = (SListNode*)malloc(sizeof(SListNode));if (ans == NULL){perror("malloc fail");return NULL;}ans->val = x;ans->next = NULL;return ans;
}


单链表打印 

原理:遍历输出即可,但链表的遍历不同于顺序表的遍历在于需要将遍历指针指向下一个结点(顺序表是下标++遍历),遇到空为止。

void SListPrint(SListNode* plist)
{SListNode* cur = plist;while (cur){printf("%d->", cur->val);cur = cur->next;}printf("NULL");
}


单链表尾插 

原理:链表的唯一缺点是不能通过下标去寻找对应结点,只能通过从头结点遍历到指定结点(因为一个结点只能通过上一个结点的指针找到,它们在内存里的存储位置不是连续的),所以,定义一个指针,从头结点开始,这里要考虑到两种情况:

1.当头结点为空时,意味着这是链表刚创建,直接将头结点指向空即可;

2.当头结点不为空时,意味着这是一个好的链表,需要遍历到该链表的末结点,将末结点的指针指向新结点完成尾插。遍历终止的条件时当前指针的下一个指针指向空,如果该指针指向空的话,遍历到末尾时会进一次循环,走到空,此时会丢失之前结点的地址。

void SListPushBack(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);//用x创建新结点if ((*pplist) == NULL){(*pplist) = newnode;}else{SListNode* cur = *pplist;while (cur->next){cur = cur->next;}cur->next = newnode;}
}


单链表的头插

原理:当头结点为空时,和尾插一样,要讲的是不为空的情况:

创建好新结点后,将新结点的下一个指针指向头结点指向的结点,然后头结点指向新结点。顺序不能对调,会丢失头结点原本指向的结点地址。

void SListPushFront(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (*pplist == NULL){*pplist = newnode;}else{newnode->next = (*pplist);*pplist = newnode;}
}


单链表的尾删

原理:动态申请的内存如果需要删除的话是需要通过free函数进行释放的。

这里也要考虑两种情况,因为单一的方法不适用于所有情况。

1.当链表有两个以上的结点时,遍历到末尾结点的前驱结点,然后释放掉下一个指针指向的结点,再置为空即可,如果遍历到删除结点的话,你释放时就会丢失掉前一个结点的地址,那个结点的指针就会变成野指针。

2.当链表为空或是只有一个结点时,直接释放即可,当然,为什么头结点为空时也能进行释放?不会构成对空指针的引用吗?我们来看看Cplusplus上面的描述:

最后一句:如果指针为空,该功能不做任何改变(因为释放完后还是为空,人为操作)。

根据free的特性,可以将空和单个结点的情况考虑进去。

void SListPopBack(SListNode** pplist)
{if ((*pplist) == NULL || (*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{SListNode* cur = *pplist;while (cur->next->next){cur = cur->next;}free(cur->next);cur->next = NULL;}
}


单链表头删

头删和尾删一样,同样也要考虑一个结点和多个结点的情况:

1.只有一个结点或为空时,和尾删一样,直接free掉即可。

2.当有多个结点时,我们需要保留头结点的下一个指针,在删除头结点后,将头结点指向刚刚保留的指针即可。

void SListPopFront(SListNode** pplist)
{if ((*pplist == NULL) || (*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{SListNode* next = (*pplist)->next;free(*pplist);*pplist = next;}
}



单链表查找

直接遍历定位即可,返回该值的结点而不是该值。

SListNode* SListFind(SListNode* plist, SLTDateType x)
{SListNode* cur = plist;while (cur){if (cur->val == x){return cur;}cur = cur->next;}return NULL;}



单链表在pos位置之后插入x

定位到pos位置后,将pos进行头插即可。

void SListInsertAfter(SListNode* pos, SLTDateType x)
{assert(pos);SListNode* newnode = BuySListNode(x);SListNode* next = pos->next;pos->next = newnode;newnode->next = next;
}



单链表删除pos位置之后的值

和插入相反,只是进行头删即可,pos在头结点上情况也一样。

void SListEraseAfter(SListNode* pos)
{assert(pos);SListNode* next = pos->next;if (next != NULL){SListNode* nextnext = next->next;free(next);pos->next = nextnext;}
}



在pos的前面插入

首先这里得考虑pos的位置,因为如果在头结点上的话就得单独考虑。

1.如果pos在头结点上的话,直接头插

2.否则,用一个前驱指针保留pos位置的前驱指针,再做插入操作。

这里断言一下,以防传来的pos和头结点为空

void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{//不允许*pphead和pos一者为空,要么都为空,要么都不空assert(*pphead);assert(pos);assert(pphead);SListNode* newnode = BuySListNode(x);if (pos == *pphead){SListPushFront(pphead, x);}else{SListNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}



删除pos位置

和上面一样,如果pos位置是头结点的话就头删,否则保留pos位置的前驱和后继指针,free掉pos后,两个指针链接。

void SLTErase(SListNode** pphead, SListNode* pos)
{assert(pphead);assert(pos);if (pos == *pphead){SListPopFront(pphead);}else{SListNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SListNode* next = pos->next;free(pos);prev->next = next;pos = NULL;}
}


销毁顺序表

从头结点开始,一个个结点往下遍历释放,最后头结点置空即可。

void SLTDestroy(SListNode** pphead)
{assert(pphead);SListNode* cur = *pphead;while (cur){SListNode* next = cur->next;free(cur);cur = next;}*pphead = NULL;}


 

相关文章:

数据结构入门(3)2.链表接口实现

目录 前言 头文件 动态申请一个结点 单链表打印 单链表尾插 单链表的头插 单链表的尾删 单链表头删 单链表查找 单链表在pos位置之后插入x 单链表删除pos位置之后的值 在pos的前面插入 删除pos位置 销毁顺序表 前言 本文将介绍链表常见的功能的实现 头文件 #…...

vscode中解决驱动编写的时候static int __init chrdev_init()报错的问题

目录 错误出错原因解决方法 错误 在入口函数上&#xff0c;出现 expected a ; 这样的提示 出错原因 缺少了 __KERNEL __ 宏定义 解决方法 补上__KERNEL__宏定义 具体做法&#xff1a;在vscode中按下ctrlshiftp &#xff0c;输入&#xff1a;C/C:Edit Configurations&#xff0…...

fastgpt本地详细部署以及配置

目录 一、Docker部署1、docker安装2、docker启动3、添加用户到 docker 组:4、验证 Docker 安装:二、one_api 本地部署1、linux系统部署2、windows系统部署三、向量模型部署(m3e)四、chatglm2模型本地部署五、fastgpt模型本地部署1、下载配置文件2、文件配置--docker-compos…...

【故障分类】基于注意力机制的卷积神经网络结合双向长短记忆神经网络CNN-BiLSTM-attention实现数据分类附matlab代码

摘要&#xff1a; ntion机制加权 4. 加权后的特征进行分类 需求分析 本文旨在实现一个通用的数据分类模型&#xff0c;可应用于不同领域的数据分类任务。 设计方案 设计一个CNN网络结构&#xff0c;提取输入数据的特征 将特征序列输入到BiLSTM网络&#xff0c;进行时序建模…...

vue接入百度地图获取经纬度

通过城市名称和城市中心经纬度来获取当前所在地图&#xff0c;当前经纬度中心获取可以通过后端获取 静态文件包&#xff0c;替换baidu.html中的ak值&#xff0c;ak值通过百度地图官方网站申请 申请&#xff1a;百度地图API申请步骤 - 知乎 代码示例文件&#xff1a; 链接&a…...

交流负载箱的特点和优势有哪些?

交流负载箱广泛应用于电力系统、新能源、轨道交通、航空航天等领域。它具有以下特点和优势&#xff1a; 1. 灵活性高&#xff1a;交流负载箱可以根据实际需求&#xff0c;调整输出电流、电压、功率等参数&#xff0c;以满足不同场景下的测试需求。同时&#xff0c;它还可以实现…...

Java线程锁之Lock的使用

Lock 的使用 Lock 是java 1.5 中引入的线程同步工具&#xff0c;它主要用于多线程下共享资源的控制。本质上Lock 仅仅是一个接口&#xff0c; 可以通过显式定义同步锁对象来实现同步&#xff0c;能够提供比synchronized 更广泛的锁定操作&#xff0c;并支持多个相关的 Lock接…...

简站wordpress主题看上去差不多 实际大不一样

有人说简站wordpress主题&#xff0c;都差不多嘛。我表示无语。表面看上去是差不多的&#xff0c;实际的细节是不一样的。 下面以编号&#xff1a;JZP4431和编号&#xff1a;JZP4878这两个主题为例子来讲一下&#xff0c;简站wordpress主题&#xff0c;在细节方面的不一样之处…...

(完美方案)解决mfc140u.dll文件丢失问题,快速且有效的修复

唉&#xff0c;又是丢失了mfc140u.dll&#xff0c;这该怎么办呢&#xff1f;如果你的电脑突然找不到或丢失mfc140u.dll文件&#xff0c;那就真是太糟糕了。别担心&#xff0c;我分享给你一些干货&#xff0c;告诉你如何快速解决mfc140u.dll丢失的问题。 一.mfc140u.dll属性功能…...

并发通信(网络进程线程)

如果为每个客户端创建一个进程&#xff08;或线程&#xff09;&#xff0c;因为linux系统文件标识符最多1024位&#xff0c;是有限的。 所以使用IO复用技术&#xff0c;提高并发程度。 阻塞与非阻塞 阻塞式复用 非阻塞复用 信号驱动IO 在属主进程&#xff08;线程中声明&…...

WPF 该线程是用不接受参数的 ThreadStart 委托创建的。

创建无参数线程是无法发去传递参数的&#xff0c;需要把 《 thread.Start(“张三”); 》改为《 thread.Start(); 》 把参数去掉就可以了。 public RegisterWindow(){InitializeComponent();//无参数线程Thread thread new Thread(pageLoad);thread.IsBackground true;//thr…...

FreeRTOS学习第9篇--队列介绍

目录 FreeRTOS学习第9篇--队列介绍1. 数据传输的方法1.1 任务之间如何传输数据1.2 队列的本质 2. 队列的工作原理和实现2.1 创建队列2.2 向队列发送数据2.3 从队列接收数据 3. 使用队列进行任务间的通信3.1 通信示例3.2 同步示例 结论 FreeRTOS学习第9篇–队列介绍 本文目标&a…...

qt如何配置ros环境

在Qt5.7的版本可以使用bash -i -c来启动qt&#xff0c;让Qt自己识别系统环境&#xff0c;不知道为什么Qt在之后的版本&#xff0c;这样使用都失效了。因为它会默认把CMAKE_PREFIX_PATH修改掉。 网上还有安装ros插件版本的qt creator&#xff0c;感觉失去了一些灵活性。 自己测试…...

20240310-1-Java后端开发知识体系

Java 基础 知识体系 Questions 1. HashMap 1.8与1.7的区别 1.71.8底层结构数组链表数组链表/红黑树插入方式头插法尾插法计算hash值4次位运算5次异或运算1次位运算1次异或运算扩容、插入先扩容再插入先插入再扩容扩容后位置计算重新hash原位置或原位置旧容量 (1) 扩容因子…...

Python基础学习(7)函数作用域与名称空间

文章目录 一.认识函数对象1.函数被引用2.函数作为元素3.函数可以作为参数和返回值 二,名称空间1.内建名称空间(存放内置函数)2.全局名称空间(Python定义在外层的名字)3.局部名称空间(存在函数内定义的名字) 三,作用域1.global 提权2.nonlocal 降权 四,匿名函数 Python基础学习(…...

使用helm部署clickhouse

&#xff08;作者&#xff1a;陈玓玏&#xff09; 前置条件 已安装 Kubernetes 集群&#xff1b; 已安装 Helm 包管理工具。 部署 1 添加 RadonDB ClickHouse 的 Helm 仓库 helm repo add ck https://radondb.github.io/radondb-clickhouse-kubernetes/ helm repo upd…...

2024.02.09 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 中国电信江苏分公司2024年春季校园招聘 校招 | 中国电信江苏分公司2024年春季校园招聘 2、校招 | 国机集团2024届总部管培生春季招聘全面启动&#xff01; 校招 | 国机集团202…...

【其他】清风眼中的《妙手仁心》

我是清风&#xff0c;一个以医生为正职&#xff0c;平时喜欢写点文字的男人。人家喜欢把我称为作家&#xff0c;可是我觉得我还配不上这个称呼。因为我所记录的只是一些身边的人和事&#xff0c;所抒发的也只是一些个人的情感&#xff0c;这与“作家”二字相去甚远。有人也许会…...

洛谷 P1036 [NOIP2002 普及组] 选数

题目描述 已知 nn 个整数 x_1,x_2,\cdots,x_nx1​,x2​,⋯,xn​&#xff0c;以及 11 个整数 kk&#xff08;k<nk<n&#xff09;。从 nn 个整数中任选 kk 个整数相加&#xff0c;可分别得到一系列的和。例如当 n4n4&#xff0c;k3k3&#xff0c;44 个整数分别为 3,7,12,1…...

SSM整合项目(删除家居 + 分页查询)

1.删除家居 1.需求分析 2.编写Service层 1.FurnService.java 添加方法 //删除家居public void del(Integer id);2.FurnServiceImpl.java 实现方法 Overridepublic void del(Integer id) {furnMapper.deleteByPrimaryKey(id);}3.单元测试 Testpublic void del() {furnService.…...

告别翻译软件!用Hunyuan-MT-7B搭建自己的多语言翻译助手

告别翻译软件&#xff01;用Hunyuan-MT-7B搭建自己的多语言翻译助手 1. 为什么需要自建翻译助手&#xff1f; 在全球化交流日益频繁的今天&#xff0c;我们每天都会遇到需要翻译的场景&#xff1a;阅读外文资料、处理国际业务邮件、浏览海外社交媒体...传统翻译软件虽然方便&…...

AutoAgent全新升级:告别流程说明,实现自主决策

在企业数字化与 AI 深度融合的当下&#xff0c;AI 不再是简单的效率工具&#xff0c;而是要成为能自主思考、主动执行、闭环优化的 “数字员工”。 此前&#xff0c;汉得灵猿&#xff08;大圣&#xff09;AI中台推出的 AutoAgent 节点V1版本 &#xff0c;通过基础自主规划能力&…...

八,附录 A:其他发现流程示例

八&#xff0c;附录 A&#xff1a;其他发现流程示例八&#xff0c;附录 A&#xff1a;其他发现流程示例8.1 修改后的发现流程8.2 优化后的发现流程8.3 高级发现流程八&#xff0c;附录 A&#xff1a;其他发现流程示例 以下部分提供了关于修改后的、优化后的和高级的发现流程的…...

mysql主键设计原则_InnoDB聚簇索引对性能的影响

主键不必是自增整数但强烈推荐&#xff1b;非自增主键&#xff08;如UUID、字符串&#xff09;易引发页分裂、随机IO和索引碎片&#xff0c;增大二级索引体积并降低缓存效率&#xff1b;更新主键等于全行重建&#xff0c;必须禁止&#xff1b;无显式主键时InnoDB会生成隐藏ROW_…...

Gophish实战指南:从零构建邮件钓鱼实验环境

1. Gophish简介与核心功能 Gophish是一款专为企业和安全团队设计的开源钓鱼模拟工具&#xff0c;它让安全测试人员能够快速搭建逼真的钓鱼攻击环境。我第一次接触这个工具是在2018年的一次内部安全演练中&#xff0c;当时我们需要测试公司员工的网络安全意识&#xff0c;但市面…...

Prompt 焚诀——一个模板,终结你和 AI 的所有沟通问题确

AI训练存储选型的演进路线 第一阶段&#xff1a;单机直连时代 早期的深度学习数据集较小&#xff0c;模型训练通常在单台服务器或单张GPU卡上完成。此时直接将数据存储在训练机器的本地NVMe SSD/HDD上。 其优势在于IO延迟最低&#xff0c;吞吐量极高&#xff0c;也就是“数据离…...

VL01N/VL02N用户必看:如何给你的交货单行项目‘贴’上专属信息标签?

VL01N/VL02N用户必看&#xff1a;如何给你的交货单行项目‘贴’上专属信息标签&#xff1f; 想象一下&#xff0c;你正在VL01N界面创建外向交货单&#xff0c;突然发现标准界面缺少客户要求的特殊包装代码。你不得不切换到Excel表格核对&#xff0c;再返回系统手工填写备注——…...

AI民主化:让每个人都能开发AI应用,是理想还是泡沫?

在人工智能&#xff08;AI&#xff09;技术飞速发展的今天&#xff0c;“AI民主化”已成为热门议题——它承诺让非专业开发者也能轻松创建AI应用&#xff0c;打破技术壁垒。然而&#xff0c;作为软件测试从业者&#xff0c;我们不禁要问&#xff1a;这究竟是推动创新的理想愿景…...

HarvestText关系网络:基于共现关系的实体社交网络构建指南

HarvestText关系网络&#xff1a;基于共现关系的实体社交网络构建指南 【免费下载链接】HarvestText 文本挖掘和预处理工具&#xff08;文本清洗、新词发现、情感分析、实体识别链接、关键词抽取、知识抽取、句法分析等&#xff09;&#xff0c;无监督或弱监督方法 项目地址:…...

Redis:延迟双删的适用边界与落地细节寺

pagehelper整合 引入依赖com.github.pagehelperpagehelper-spring-boot-starter2.1.0compile编写代码 GetMapping("/list/{pageNo}") public PageInfo findAll(PathVariable int pageNo) {// 设置当前页码和每页显示的条数PageHelper.startPage(pageNo, 10);// 查询数…...