数据结构入门(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;}


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/737473.shtml

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

相关文章

《互联网的世界》第六讲-去中心化和安全

互联网构建于开放互联的中立原则之上&#xff0c;公平接入&#xff0c;数据互联互通&#xff0c;流量被无差别对待&#xff0c;这意味着互联网本质上是匿名&#xff0c;去中心的&#xff0c;这与我们的现实世界完全不同。 但互联网上的主流业务却是 c/s 产销模式&#xff0c;试…

JAVA实战开源项目:校园失物招领管理系统(Vue+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 招领管理模块2.2 寻物管理模块2.3 系统公告模块2.4 感谢留言模块 三、界面展示3.1 登录注册3.2 招领模块3.3 寻物模块3.4 公告模块3.5 感谢留言模块3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 校园失物招领…

STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置

STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置前言第1章 设置字体颜色第2章 设置字体大小第3章 设置代码区背景颜色总结 前言 编程软件环境最好就设置一个自己喜欢的界面进行显示&#xff0c;这样看起来会比较舒服些…

026—pandas 根据文本数据提取特征

前言 在数据处理中&#xff0c;源数据可能具有一定便于记录但又复杂的结构&#xff0c;我们在后续使用数据时还需要进一步进行处理。在本例中&#xff0c;要根据一列数据提取出数据中的相关特征&#xff0c;我们来看看 pandas 是如何完成的。 需求&#xff1a; 以上数据的 a …

CKB转型为BTC Layer2后月涨超 300%,还有哪些转型热门赛道的老项目?

虽然说牛市下&#xff0c;炒新不炒旧。但一些渡过漫长熊市的老牌项目方&#xff0c;重新回到牌桌前开始新叙事后&#xff0c;市场依然有人买单。 部分项目方已经初步尝到了甜头&#xff0c;Arweave&#xff08;AR&#xff09;宣布从去中心化数据存储转换到「以太坊杀手」后&am…

网络攻防中nginx安全配置,让木马上传后不能执行、让木马执行后看不到非网站目录文件、命令执行后权限不能过高

网络攻防中nginx安全配置,让木马上传后不能执行、让木马执行后看不到非网站目录文件、命令执行后权限不能过高。 0x01 Nginx介绍 nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端。nginx一般是把请求发…

腾讯qlv格式转换mp4,亲测可解决,免费领取

问题描述 最近想兼职做自媒体,最初想法是想把腾讯视频上的资源下载到本地,本地做一些剪辑和图文配音发布到自媒体app上,但是我还是幼稚了,下载到腾讯的视频居然是qlv加密的,用自带的腾讯视频才能看,网上找了一大堆转换方法,全是广告,什么cmd进去用命令行转的,什么找到…

大数据 - Spark系列《十三》- spark集群部署模式

Spark系列文章&#xff1a; 大数据 - Spark系列《一》- 从Hadoop到Spark&#xff1a;大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 大数据 - Spark系列《…

五、OpenAI实战之Assistants API

在8线小城的革委会办公室里&#xff0c;黑8和革委会主任的对话再次展开。 黑8&#xff1a;主任&#xff0c;您知道吗&#xff1f;除了OpenAI API&#xff0c;现在还有一项新的技术叫做Assistants API&#xff0c;它可以帮助我们更好地进行对话和沟通。 主任&#xff1a;Assis…

Java网络编程详解

目录 网络编程 1、概述 2、网络通信的要素 3、IP 4、端口 5、通信协议 6、TCP 文件上传 Tomcat 7、UDP 单方发送单方接受 双方发送接收 8、URL URL测试 URL下载网络资源 网络编程 1、概述 信件&#xff1a; 计算机网络&#xff1a; 计算机网络是指将地理位置不…

WPF —— TextBlock、LineBreak RadioButton控件详解

一:TextBlock 1&#xff1a;TextBlock 简介 <LineBreak/> 换行 显示文本 标签内容和content属性共存 2、TextBlock 常用的属性 Foreground&#xff1a;TextBlock的文本内容的颜色。 Background&#xff1a;背景&#xff0c;获取或设置要用于填充内容区域背景的 Brush…

冒泡排序的理解与实现【C语言、C++、java】

冒泡排序介绍 冒泡排序(Bubble Sort)&#xff0c;又被称为气泡排序或泡沫排序。 它是一种较简单的排序算法。它会遍历若干次要排序的数列&#xff0c;每次遍历时&#xff0c;它都会从前往后依次的比较相邻两个数的大小&#xff1b;如果前者比后者大&#xff0c;则交换它们的位…

一体机电脑辐射超标整改

电脑一体机是目前台式机和笔记本电脑之间的一个新型的市场产物&#xff0c;它将主机部分、显示器部分整合到一起的新形态电脑&#xff0c;该产品的创新在于内部元件的高度集成。随着无线技术的发展&#xff0c;电脑一体机的键盘、鼠标与显示器可实现无线链接&#xff0c;机器只…

美国站群服务器使用技巧与注意事项

美国站群服务器使用技巧与注意事项有哪些?RAKsmart小编为您整理发布美国站群服务器使用技巧与注意事项&#xff0c;希望对您有帮助。 美国站群服务器的使用技巧主要包括远程管理、灵活配置和备份还原&#xff0c;具体如下&#xff1a; 1. **远程管理**&#xff1a;用户可以通过…

计算机网络-第5章 运输层(2)

5.6 TCP可靠传输实现 以字节为单位的滑动窗口。 发送窗口已满&#xff0c;停止发送。 发送和接收的数据都来自缓存。 超时重传时间RTO选择&#xff1a;自适应算法&#xff0c; 选择确认SACK&#xff1a;只传送缺少的数据。大多数实现还是重传所有未被确认的数据块。 5.7 TCP的…

LLM 推理优化

LLM 推理服务重点关注两个指标&#xff1a;吞吐量和时延&#xff1a; 吞吐量&#xff1a;主要从系统的角度来看&#xff0c;即系统在单位时间内能处理的 tokens 数量。计算方法为系统处理完成的 tokens个数除以对应耗时&#xff0c;其中 tokens 个数一般指输入序列和输出序列长…

掌握Mongodb,看完这篇文章就够了

目录 1.概念 2.操作 2.1数据库操作 2.2集合操作 2.3数据操作 3.查询 4.常用技术 5.python与MongoDB 1.概念 MongoDB是一种非关系型数据库&#xff08;NoSQL&#xff09;&#xff0c;它以灵活的文档存储格式&#xff08;BSON&#xff09;和强大的查询能…

MinGW-w64的下载与安装

文章目录 1 下载2 安装3 配置环境变量4 验证 1 下载 官网地址&#xff1a;https://www.mingw-w64.org/github地址&#xff1a;https://github.com/niXman/mingw-builds-binaries/releases windows下载 跳转github下载 版本号选择&#xff1a;13.2.0是GCC的版本号&#xff1b…

如何避免MYSQL主从延迟带来的读写问题?

在MYSQL 部署架构选型上&#xff0c;许多公司都会用到主从读写分离的架构&#xff0c;如下是一个一主一从的架构&#xff0c;主库master负责写入&#xff0c;从库slave进行读取。 但是既然是读写分离&#xff0c;必然会面临这样一个问题&#xff0c;当在主库上进行更新后&#…

QML | 在QML中导入JavaScript资源、导入JavaScript资源、包含一个JavaScript 资源

01 在QML中导入JavaScript资源 JavaScript资源可以被QML文档和其他JavaScript通过相对或者绝对路径进行导入。如果使用相对路径,位置解析需要相对于包含import语句的QML文档或JavaScript资源的位置。如果JavaScript需要从网络资源中进行获取,组件的status属性会被设置为Loadi…