单链表的学习与基础运用p

news2024/10/6 2:34:35

当我们在实际做项目,或者是自主开发一点小东西的时候,往往会储存一些数据,有时候我们需要添加这些数据,有时候需要删除,而有时候,仅仅只需要查找到就行。链表中的每一个节点都是一个独立开辟的空间,就像一个个的小箱子。那我们要如何将这些箱子串联起来呢?这时候,链表就发挥了作用。一个最基本的节点,应当如下图组成

typedef char x;
typedef struct SlistNote SlistNote;

struct SlistNote
{
	x data;
	SlistNote* next;
};

因为我们可能需要不断的改变数据的类型,所以在最初我们利用typedef来进行重定义。并且因为结构体指针每次创建名都太长,索性直接将名字进行替换

而上图最重要的,其实是结构体中的内容:1.数据。在这个节点中存放着相应的数据  2.指向下一个节点的地址。如上图的next,便是指向下一个节点的地址。

因此,当我们想使用一个链表的时候,我们其实只要找到第一个节点的地址就可以了。

那么,我们要如何实现链表的初始化,前插后插,前删后删,查询,定点操作呢?让我们一个一个来。

初始化

SListNote* SltBuyNote(SLT_type x)
{
	SListNote* newnote = (SListNote*)malloc(sizeof(SListNote));
	assert(newnote);
	newnote->data = x;
	newnote->next = NULL;
	return newnote;
}

我们想要实现尾插和头插,需要先把要插入的节点准备好。以上代码,便是数据的初始化过程。先开辟出一片空间,并将这个空间的地址赋值给newnote这个指针。接着进行assert,避免前面的开辟空间失败进而导致后续的一系列错误。接着将数据进行赋值,暂时先把next指针定义为空指针,防止变成野指针,接着将刚刚创建的这个指针给return了。

尾插

void BackInsert(SListNote** pphead, SLT_type x)
{
	SListNote* newnote = SltBuyNote(x);
	if (*pphead == NULL)
	{
		*pphead = newnote;
	}
	else
	{
		SListNote* ppend = *pphead;
		while (ppend->next)
		{
			ppend = ppend->next;
		}
		ppend->next = newnote;
	}
}

当我们知道如何初始化节点以后,我们便可以开始一些基本的操作,比如尾插。在最开始,我们先创建出一个节点newnote,这个节点内部的数据就是我们要插入的数据。接着,我们判断一下被插入的节点的是否为空,若为空,则直接将newnote设置为初始节点,若不为空,那便先通过while循环找到ppend,也就是该结构体的末端。接着让结构体末端的next指针指向newnote,那便完成了尾插。

头插

void FrontInsert(SListNote** pphead, SLT_type x)
{
	SListNote* newnote = SltBuyNote(x);
	if (*pphead == NULL)
	{
		*pphead = newnote;
	}
	else
	{
		newnote->next = *pphead;
		*pphead = newnote;
	}
}

头插相比较于尾插要更简单一些,前面基本相似,在else这边,我们只需要把新节点的next指针指向*pphead,那其实就已经插上了。但是这样有一些错误,因为此时链表的头部已经发生改变,变成了newnote,因此,我们需要手动把节点地址改为newnote地址。

头删

void FrontDel(SListNote** pphead)
{
	assert(pphead && *pphead);

	SListNote* pcur = *pphead;
	if (pcur->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	SListNote* pcur = *pphead;
	*pphead = pcur->next;
	free(pcur);
}

头删也是比较简单的,在头删函数中,我们首先需要先判断到底有没有数据,利用assert函数完成,如果有,再判断有几个数据,如果只有一个,那便是将头地址给删除,如果多于一个,那就将原先的头地址赋给一个值做备份,接着将头地址改变为下一个节点地址,再释放掉之前的头地址,即可完成头删。

尾删

void BackDel(SListNote** pphead)
{
	assert(pphead && *pphead);

	SListNote* pcur = *pphead;
	if (pcur->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		while (pcur->next->next)
		{
			pcur = pcur->next;
		}
		free(pcur->next);
		pcur->next->next = NULL;
		pcur->next = NULL;
	}

尾删前面几部类似于头删,如果已经确定有大于1个的数据,那就利用while精确定位到最后一个数据处,接着释放掉最后一个数据的地址并赋NULL值。

指定位置删除

void PosDel(SListNote** pphead, int pos)
{
	int count = 0;
	SListNote* pcur = *pphead;
	assert(pphead && *pphead);
	if (pos == 0)
	{
		FrontDel(pphead);
	}
	else
	{
		while (pcur)
		{
			pcur = pcur->next;
			count++;
		}
		pcur = *pphead;
		count = 0;
		while (count < pos - 1)
		{
			pcur = pcur->next;
			count++;
		}
		SListNote* ppos = pcur->next;
		pcur->next = pcur->next->next;
		free(ppos);
		ppos = NULL;
	}
}

我们先断言待删链表不是空链表,接着看待删位置是不是首节点,如果是首节点,那么直接执行头删,如果不是,则接着进行下一步。通过while循环找到pos位置处的节点,接着将这个节点的上一个节点的next指针连接到pos位置的下一个节点,接着删除pos位置处的节点,将其free掉。

指定位置插入

指定位置插入分为前插和后插,不同的插入方式需要不同的代码来实现

前插:

void FrontPosInsert(SListNote** pphead, int pos, SLT_type x)
{
	SListNote* newnote = SltBuyNote(x);
	if (*pphead == NULL)
	{
		*pphead = newnote;
	}
	else
	{
		if (pos == 0)
		{
			FrontInsert(pphead, x);
		}
		else
		{
			SListNote* pcur = *pphead;
			int count = 0;
			while (count != pos-1)
			{
				pcur = pcur->next;
				count++;
				if (pcur == NULL)
				{
				printf("不在可执行范围内!");
				return 0;
				}

			}
				SListNote* ppos = pcur->next;
				pcur->next = newnote;
				newnote->next = ppos;
		}
	}
}

先创建一个节点newnote,接着判断链条是否为空链条,若是空链条,则将*pphead直接赋一个newnote,若不是,则开始判断pos的数值,若pos为0的话,那么就执行前插函数,若pos不为0,则在进行下一步。先找到pos所代表的节点的前一个节点,接着继续判断,若该节点已经超过已有的节点,则进行提醒并直接返回,当然,你也可以选择进行一次后插。若该pos符合以上规则,则开始进行插入。

后插

void BackPosInsert(SListNote** pphead, int pos, SLT_type x)
{
	SListNote* newnote = SltBuyNote(x);
	if (*pphead == NULL)
	{
		*pphead = newnote;
	}
	else
	{
		SListNote* pcur = *pphead;
		int count = 0;
		while (count != pos)
		{
			pcur = pcur->next;
			count++;
			if (pcur == NULL)
			{
				printf("不在可执行范围内!");
				return 0;
			}
		}
		SListNote* ppos = pcur->next;
		pcur->next = newnote;
		newnote->next = ppos;
	}
}

尾插与头插大体相似,在一些细节处略微改动,例如在后续找pos位置时,我们找到的是pos的位置,而之前是找到pos前面一个节点,这方面略有不同。其他大体相同。

查找节点

void Finding(SListNote** pphead, SLT_type x)
{
	assert(pphead && *pphead);
	SListNote* pcur = *pphead;
	int count = 0;
	while (pcur)
	{
		if (pcur->data == x)
		{
			printf("找到了!在%d处\n", count);
			return;
		}
		count++;
		pcur = pcur->next;
	}
	printf("没找到");
}

查找节点并不难,用到的方法和之前许多代码相似,可大致看看上图。

摧毁链表

void Sli_destory(SListNote** pphead)
{
	assert(pphead && *pphead);
	SListNote* pcur = *pphead;
	while (pcur)
	{
		SListNote* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;

首先我们也还是先断言一下节点地址的存在性,接着从头到尾一个节点一个节点的去删除,为了方便显示,我在最后又让首节点显示了个NULL,已证明已经删除完成。

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

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

相关文章

Java基础-内部类与异常处理

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、Java 内部类 什么是内部类&#xff1f; 使用内部类的优点 访问局部变量的限制 内部类和继承 内部…

一位3D打印工程师繁忙的一天

早晨&#xff1a;准备与规划 7:00 AM - 起床与晨练 3D打印工程师早起进行晨练&#xff0c;如跑步或瑜伽&#xff0c;以保持身心健康。晨练后&#xff0c;享用一顿健康的早餐&#xff0c;为一天的繁忙工作做好准备。 8:00 AM - 检查邮件和项目进展 在开始工作前&#xff0c;先…

封装了一个仿照抖音效果的iOS评论弹窗

需求背景 开发一个类似抖音评论弹窗交互效果的弹窗&#xff0c;支持滑动消失&#xff0c; 滑动查看评论 效果如下图 思路 创建一个视图&#xff0c;该视图上面放置一个tableView, 该视图上添加一个滑动手势&#xff0c;同时设置代理&#xff0c;实现代理方法 (BOOL)gestur…

Zkeys三方登录模块支持QQ、支付宝登录

1&#xff0c;覆盖到根目录&#xff0c;并导入update.sql数据库文件到Zkeys数据库里 2. 后台系统权限管理&#xff0c;配置管理员权限-系统类别-找到云外科技&#xff0c;全部打勾 3&#xff0c;后台系统设置找到云外快捷登录模块填写相应的插件授权配置和登录权限配置&#x…

【python中级】图像从从笛卡尔坐标系转换为极坐标系

【python中级】图像从从笛卡尔坐标系转换为极坐标系 1.背景2.生成二维图3.极坐标转换1.背景 笛卡尔坐标系就是我们常说的直角坐标系。 笛卡尔坐标系,也称为直角坐标系,是由法国数学家和哲学家勒内笛卡尔(Ren Descartes)发明的一种二维或三维坐标系统。它使用两个或三个相互…

人工智能在病理切片虚拟染色及染色标准化领域的系统进展分析|文献速递·24-07-07

小罗碎碎念 本期文献主题&#xff1a;人工智能在病理切片虚拟染色及染色标准化领域的系统进展分析 这一期文献的速递&#xff0c;是有史以来数量最大的一次&#xff0c;足足有十一篇&#xff0c;本来打算分两期写&#xff0c;但是为了知识的系统性&#xff0c;我决定咬咬牙&…

texStudio使用(小白)

原先使用overleaf在线编译&#xff0c;可能eps格式的图片太大导致需要充钱&#xff0c;所以考虑本地安装 安装教程参考B站视频&#xff1a;B站Latex本地编译器安装&#xff1a;TexLive TextStudio 踩到坑&#xff1a; 1. 编译器位置要选择对 因为BibTex选成了Biber导致出现无…

minist数据集分类模型的训练

minist数据集训练 训练方法&#xff1a;利用pytorch来实现minist数据集的分类模型训练 训练模型如下图所示 模型代码&#xff1a; import torch from torch import nn from torch.nn import Flattenclass Net(nn.Module):def __init__(self):super().__init__()self.module …

文件管理下:文件函数的学习

前言 Hello,小伙伴们你们的作者君又来了&#xff0c;上次我们简单介绍了文件的坐拥并简单提到了数据的读取&#xff0c;和C语言的默认流的作用&#xff0c;今天我将继续带领大家探索文件的奥秘&#xff0c;大家准别好了吗&#xff1f; 在内容开始之前还是按照惯例&#xff0c…

**kwargs 字典解包传参的方式

字典解包传参 在Python中&#xff0c;****kwargs**是一种通过字典解包 (dictionary unpacking) 的方式进行参数传递的方式。它将一个字典的键值对解包并传递给函数的命名参数。 示例代码 kwargs实参: {name: "jordan", age: 18, score: [80, 85, 85]} get_info形…

下载linux的吐槽

本来这几天放假了&#xff0c;想下一个linux玩一玩 教程&#xff08;我就是根据这个教程进行下载的&#xff0c;但是呢在进行修改BIOS 模式的 地方遇见了困难&#xff0c;也许是电脑修过的原因&#xff0c;我狂按F12 以及 FnF12都没有BIOS设置&#xff0c;只有一个让我选择用w…

前端扫盲:cookie、localStorage和sessionStorage

cookie、localStorage和sessionStorage都是存储数据的方式&#xff0c;他们之间有什么不同&#xff0c;各有什么应用场景&#xff0c;本文为您一一解答。 一、什么是cookie、localStorage和sessionStorage 1. Cookie是一种存储在用户计算机上的小型文本文件&#xff0c;由服务…

子数组按位与为k

注意这里的子数组是连续的非空的数组&#xff0c;我们要学会与处理就是求交集 class Solution { public:long long countSubarrays(vector<int>& nums, int k) {long long ans 0;for (int i 0; i < nums.size(); i) {int x nums[i];for (int j i - 1; j > …

通过消息传递同步操作

通信顺序进程&#xff08;CSP&#xff09; 是一种形式语言&#xff0c;用来描述并发性系统间进行交互的模式 每个线程或进程独立运行&#xff0c;它们之间仅通过消息传递进行通信&#xff0c;而不是直接共享状态 每个线程实际上都是一个状态机&#xff1a;当它接收到一条消息时…

Zabbix监控软件

目录 一、什么是Zabbix 二、zabbix监控原理 三、zabbix 安装步骤 一、什么是Zabbix ●zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 ●zabbix 能监视各种网络参数&#xff0c;保证服务器系统的安全运营&#xff1b;并提供灵活的…

基于LoFTR_TRT项目实现LoFTR模型的trt推理与onnx推理,3060显卡下320图像30ms一组图

本博文主要记录了使用LoFTR_TRT项目将LoFTR模型导出为onnx模型&#xff0c;然后将onnx模型转化为trt模型。并分析了LoFTR_TRT与LoFTR的基本代码差异&#xff0c;但从最后图片效果来看是与官网demo基本一致的&#xff0c;具体可以查看上一篇博客记录。最后记录了onnx模型的使用【…

深入探索 Python 中的数据维数:高维数据处理方法与应用

Python 数据维数 在数据科学和机器学习领域&#xff0c;理解数据的维度是至关重要的。Python作为一种强大而灵活的编程语言&#xff0c;提供了丰富的工具和库来处理各种维度的数据。本文将介绍Python中数据维数的概念&#xff0c;以及如何使用Python库来处理不同维度的数据。 什…

27 防火墙不同区域之间是如何通信

26 华三防火墙安全区域-CSDN博客 目标实现不同区域的通信 1 给防火墙配置IP地址 WEB页面配置IP地址 2 在PC机上配置对应对IP地址 &#xff08;该要启用的接口一定要启用 IP地址 子网掩码 网关 一定要查看好&#xff09; 3 将配置好的IP地址对应的不同接口加入到不同的区域上去 …

关于忠诚:忠于自己的良知、理想、信念

关于忠诚&#xff1a; 当我们面对公司、上司、爱人、恋人、合作伙伴还是某件事&#xff0c;会纠结离开还是留下&#xff0c;这里我们要深知忠诚的定义&#xff0c;我们不是忠诚于某个人、某件事、或者某个机构&#xff0c;而是忠诚于自己的良知&#xff0c;忠诚于自己的理想和…

【计算机毕业设计】020基于weixin小程序订餐系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…