单链表<数据结构 C版>

news2024/9/21 4:36:33

目录

概念

 链表的单个结点

 链表的打印操作

新结点的申请

尾部插入

头部插入

尾部删除

头部删除

查找

在指定位置之前插入数据

在任意位置之后插入数据

测试运行一下:

 删除pos结点

 删除pos之后结点

 销毁链表


概念

单链表是一种在物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接顺序实现的。

链表的每个结点有两个部分,分别是数据和指向下个结点的指针,每个链表的最后一个结点的下一个结点为NULL(不能对NULL解引用)。

放一张bit课件里的图,我觉得很形象:


 链表的单个结点

typedef int SLDataType;//重定义一下在链表内存放的数据类型,方便后期对类型进行统一修改

//链表的单个结点
typedef struct SListNode {//Single List Node :链表结点
	SLDataType data;//存放的数据
	struct SListNode* next;//指向下一个结点的指针
}SLNode;//重定义名字方便后期使用

 链表的打印操作

//链表的打印操作
void SLPrint(SLNode* phead) {
	assert(phead);//不能传入空指针
	SLNode* pcur = phead;
	//pointer cursor:指针光标,不让头结点丢失(虽然不会改变头结点的指向)
	while (pcur) {//等同于pcur!=NULL
		printf("%d->", pcur->data);//打印此结点的数据
		pcur = pcur->next;//使pcur指向下一个结点
	}
	printf("NULL\n");
}

新结点的申请

后面会涉及到新结点的插入,申请新结点可以封装成一个函数,避免代码冗余

//新结点的申请
SLNode* SLBuyNode(SLDataType x) {
	SLNode* node = (SLNode*)malloc(sizeof(SLNode));
	if (!node) {//返回值为空,申请失败(一般是空间不足了),直接退出
		perror("malloc fail");
		exit(1);
	}
	node->data = x;//将数据赋给data
	node->next = NULL;//将下一个节点置为NULL;
	return node;
}

尾部插入

//尾部插入
void SLPushBack(SLNode** pphead, SLDataType x) {
	//注意在这里我们传参的是二级指针,因为我们需要在函数内部改变头结点的指向
	assert(pphead);//不能传NULL
	//新结点的申请
	SLNode* node=SLBuyNode(x);
	if (*pphead == NULL) {
		*pphead = node;
	}
	else {
		SLNode* pcur = *pphead;
		while (pcur->next) {//找到next元素为NULL的结点,也就是为链表尾部
			pcur = pcur->next;
		}
		pcur->next = node;
	}
	
}

测试运行一下:


头部插入

//头部插入
void SLPushFront(SLNode** pphead, SLDataType x) {
	assert(pphead);
	SLNode* node = SLBuyNode(x);
	//这里需要处理头结点为空的情况吗?不需要,因为没有涉及到解引用其元素
	node->next = *pphead;
	*pphead = node;
}

测试运行一下:


尾部删除

//尾部删除
void SLPopBack(SLNode** pphead) {
	assert(*pphead && pphead);//
	if (!(*pphead)->next) {//处理只有一个元素的情况
		free(*pphead);
		*pphead = NULL;
	}
	else {
		SLNode* prev = NULL;
		SLNode* pcur = *pphead;
		while (pcur->next) {//找到尾结点前一个结点
			prev = pcur;
			pcur = pcur->next;
		}
		free(pcur);//将尾结点释放
		pcur = NULL;
		prev->next = NULL;//将尾结点的前一个结点的next元素置为NULL
	}
}

测试运行一下:


头部删除

//头部删除
void SLPopFront(SLNode** pphead) {
	assert(*pphead && pphead);
	SLNode* next = (*pphead)->next;//保存头结点的下一个结点地址
	free(*pphead);//释放头结点
	*pphead = next;//使头结点指向下一个结点
}

测试运行一下:


查找

在链表中想要对指定位置进行操作不能使用下标,所以我们必须找到指定位置的地址才能对其进行操作。

//查找
SLNode* SLFind(SLNode* phead, SLDataType x) {
	assert(phead);
	SLNode* pcur = phead;
	while (pcur) {
		if (pcur->data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

在指定位置之前插入数据

//在指定位置之前插入数据
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x) {
	assert(pphead && pos && *pphead);//pos和pphead不能为空,以及pphead指向空间不能为空
	if (*pphead == pos) {//处理头插的情况
		SLPushFront(pphead,x);
	}
	else {
		SLNode* node = SLBuyNode(x);
		SLNode* pcur = *pphead;
		while (pcur->next != pos) {//找到pos前一个结点
			pcur = pcur->next;
		}
		node->next = pcur->next;
		pcur->next = node;
	}
}

测试运行一下:


在任意位置之后插入数据

//在任意位置之后插入数据
void SLInsertAfter(SLNode* pos, SLDataType x) {
	assert(pos);//pos不能为空
	SLNode* node = SLBuyNode(x);
	node->next = pos->next;
	pos->next = node;
}

测试运行一下:


 删除pos结点

//删除pos结点
void SLErase(SLNode** pphead, SLNode* pos) {
	assert(*pphead && pphead && pos);
	if (*pphead == pos) {//处理头删的情况
		SLPopFront(pphead);
	}
	else {
		SLNode* pcur = *pphead;
		while (pcur->next!= pos) {
			pcur = pcur->next;
		}
		pcur->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

 测试运行一下:


 删除pos之后结点

//删除pos之后结点
void SLEraseAfter(SLNode* pos) {
	assert(pos && pos->next);//pos后面的结点也不能为空
	SLNode* next = pos->next;
	pos->next = next->next;
	free(next);
	next = NULL;
}

 测试运行一下:

 


 销毁链表

//销毁链表
void SLDestory(SLNode** pphead) {
	assert(pphead && *pphead);
	SLNode* pcur = *pphead;
	while (pcur) {
		SLNode* nextnode = pcur->next;//使用一个变量接受下一个结点地址
		free(pcur);
		pcur = nextnode;
	}
	*pphead = NULL;
}

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

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

相关文章

Golang | Leetcode Golang题解之第264题丑数II

题目&#xff1a; 题解&#xff1a; func nthUglyNumber(n int) int {dp : make([]int, n1)dp[1] 1p2, p3, p5 : 1, 1, 1for i : 2; i < n; i {x2, x3, x5 : dp[p2]*2, dp[p3]*3, dp[p5]*5dp[i] min(min(x2, x3), x5)if dp[i] x2 {p2}if dp[i] x3 {p3}if dp[i] x5 {p5…

【PostgreSQL教程】PostgreSQL 选择数据库

博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

图论模型-迪杰斯特拉算法和贝尔曼福特算法★★★★

该博客为个人学习清风建模的学习笔记&#xff0c;部分课程可以在B站&#xff1a;【强烈推荐】清风&#xff1a;数学建模算法、编程和写作培训的视频课程以及Matlab等软件教学_哔哩哔哩_bilibili 目录 ​1图论基础 1.1概念 1.2在线绘图 1.2.1网站 1.2.2MATLAB 1.3无向图的…

基于SpringBoot+Vue的校园疫情防控系统(带1w+文档)

基于SpringBootVue的校园疫情防控系统(带1w文档) 基于SpringBootVue的校园疫情防控系统(带1w文档) 主要对首页、个人中心、学生管理、疫情动态管理、知识信息管理、防疫教育管理、健康打卡管理、请假申请管理、出校登记管理、入校登记管理、核酸报告管理、交流论坛、系统管理的…

MySQL的建表及查询

一。建立表 mysql> create table student(id int(10) not null unique primary key,name varchar(20) not null,sex varchar(4),birth year,department varchar(20),address varchar(50)); mysql> create table score(id int(10) not null unique primary key auto_incr…

精明选择施工项目管理工具的实用建议

国内外主流的10款施工项目进度管理软件对比&#xff1a;PingCode、Worktile、Contractor Foreman、建设工程项目管理平台&#xff08;JSGC&#xff09;、智慧工地综合管理系统、工程项目信息管理系统&#xff08;GCXX&#xff09;、Buildertrend、Procore、Autodesk Constructi…

Edge侧边栏copilot消失

Edge侧边栏copilot消失 当前环境 自己ip问题已解决&#xff0c;edge中已登录账号&#xff0c;地区已设置为美国&#xff0c;语言已设置为英文。具体可以通过空白页右上角的setting验证 解决方案 首先&#xff0c;打开“任务管理器”&#xff0c;在其中找到 Microsoft Edge…

【C语言】动态内存管理(下)(realloc函数)

文章目录 前言1. realloc2. realloc函数在调整空间时的细节2.1 针对情况1&#xff08;realloc后面有足够的内存空间&#xff09;2.2 针对情况2&#xff08;realloc后面没有足够的内存空间&#xff09;2.3 realloc函数使用的注意事项2.4 realloc的使用实例2.5 realloc函数的补充…

ubuntu安装mysql8.0

文章目录 ubuntu版本安装修改密码取消root跳过密码验证 ubuntu版本 22.04 安装 更新软件包列表 sudo apt update安装 MySQL 8.0 服务器 sudo apt install mysql-server在安装过程中&#xff0c;系统可能会提示您设置 root 用户的密码&#xff0c;请务必牢记您设置的密码。…

产线中有MES系统 还有安装SCADA的必要吗?

MES系统即制造执行系统&#xff08;Manufacturing Execution System&#xff09;&#xff0c;是一种面向车间层的管理信息系统&#xff0c;旨在通过信息传递优化从订单下达到产品完成的全过程管理。 MES可以为企业提供包括制造数据管理、计划排程管理、生产调度管理、库存管理、…

网路布线和数值转换

文章目录 信号的分类数字信息的优势双绞线分类双绞线标准与分类 光纤的特点光纤分为单模光纤和多模光纤 光纤接口双绞线的连接规范EIA/TIA-568A和568B 线缆的连接综合布线系统无线电波的传输方式 数制转换十进制转二进制计算机的数值 信号的分类 1.模拟信号 2.数字信号 数字信…

动态住宅IP和静态住宅IP使用上有差异吗?

在互联网连接的世界中&#xff0c;IP地址是我们识别和访问网络资源的关键。住宅IP地址&#xff0c;特别是动态住宅IP和静态住宅IP&#xff0c;是两种不同类型的IP分配方式&#xff0c;它们在使用和功能上存在显著差异。 1. IP地址的稳定性 动态住宅IP&#xff1a;这种IP地址是…

七月份信息课总结

总结 七月份信息课总结算法记录线性代数&#xff1a;数论&#xff08;这是信竞生和数竞生都最难跨出的一步&#xff09;&#xff1a;动态规划&#xff08;~~DP万岁&#xff01;&#xff01;&#xff01;~~&#xff09;组合数学&#xff08;恶心&#xff0c;但我很喜欢&#xff…

Python爬虫-淘宝搜索热词数据

前言 本文是该专栏的第70篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者有详细针对“亚马逊Amazon搜索热词”数据采集的详细介绍,对此感兴趣的同学,可以往前翻阅《Python爬虫-某跨境电商(AM)搜索热词》进行查看。 而在本文,笔者将以淘宝为例,获取…

Linux----Mplayer音视频库的移植

想要播放视频音乐就得移植相关库到板子上 Mplayer移植需要依赖以下源文件&#xff1a;(从官网获取或者网上) 1、zlib-1.2.3.tar.gz &#xff1a;通用的内存空间的压缩库。 2、libpng-1.2.57.tar.gz :png格式图片的压缩或解压库 3、Jpegsrc.v9b.tar.gz : jpeg格式图片的压…

linux配置podman阿里云容器镜像加速器

1.下载podman yum install -y podman systemctl status podman systemctl start podman 2.获取阿里云个人容器镜像加速器地址 访问阿里云官网&#xff1a;首先&#xff0c;您需要访问阿里云&#xff08;Alibaba Cloud&#xff09;的官方网站。阿里云官网的URL是&#xff1a;…

医疗器械维修人员培训的重要性及其操作策略

医疗器械维修人员培训的重要性及其操作策略是确保医疗器械持续、安全、有效运行的关键。以下是对其重要性的解释以及相应的操作策略&#xff1a; 医疗器械维修人员培训的重要性 确保患者安全 经过培训的维修人员能够更准确地诊断问题&#xff0c;及时修复设备&#xff0c;避…

【IntelliJ IDEA】一篇文章集合所有IDEA的所有设置

IntelliJ IDEA 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;其设置涵盖了多个方面&#xff0c;以满足不同开发者的需求和偏好。由于 IDEA 的设置相当复杂和详尽&#xff0c;这里无法在一篇简短的文章中详细介绍所有设置。然而&#xff0c;我可以提供一…

轻松掌握:两个方法合并ZIP分卷压缩包

在文件传输和存储过程中&#xff0c;为了绕过文件大小限制或优化下载速度&#xff0c;我们常常会将大型文件分割成多个较小的ZIP分卷压缩包。然而&#xff0c;在接收这些分卷后&#xff0c;如何正确地将它们合并回原始的ZIP文件&#xff0c;可能是许多用户面临的一个问题。本文…

LeetCode两数相加

给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 开头。…