实现了单链表各种功能,并配上详细解读。

news2024/11/16 11:33:00

单链表

  • 链表的概念及结构
  • 链表的分类
  • 链表的实现
    • 初始化
    • 打印
    • 申请结点
    • 头插
    • 尾插
    • 头删
    • 尾删
    • 查找
    • 在pos位置之后插入
    • 在pos位置之前插入
    • 删除pos位置之后的值
    • 删除pos位置的值
    • 销毁

链表的概念及结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
在这里插入图片描述

链表的分类

单向或双向
在这里插入图片描述
在这里插入图片描述
带头或不带头
在这里插入图片描述
在这里插入图片描述
循环或不循环
在这里插入图片描述
在这里插入图片描述
虽然有这么多的链表结构,但是我们常用的就两种
无头单向不循环链表
在这里插入图片描述
带头双向循环链表
在这里插入图片描述

链表的实现

实现的是一个无头的单链表

初始化

	//链表的初始化
	SLTNode* plist = NULL;

打印

//打印
void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

申请结点

//申请结点
SLTNode* BuySlistNode(SLTDatatype x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

头插

//头插
void SListPushFront(SLTNode* phead, SLTDatatype x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = phead;
	phead = newnode;
}

根据前面的代码,我们头插结点,并打印试试看看代码对不对?
在这里插入图片描述
打印NULL,难道是我们代码写错了吗?
考虑这样一个问题,头插的时候,我们需要改变头指针的地址,那就调试一下看看,地址到底改变了吗
在这里插入图片描述
在这里插入图片描述
看到这里发现了问题,形参的改变并不会影响实参
举一个相似但很简单的例子,比如交换x,y的值
在这里插入图片描述
这里也是形参的改变并不会影响实参,那我们改如何改变x,y的值呢?答案是传址调用
在这里插入图片描述
改变int类型我们传地址,如果改变int* 我们该传什么呢?答案是传int* 的地址
在这里插入图片描述
在这里插入图片描述
所以我们得出这样的结论,改变结构体就传结构体的地址改变结构体指针就传结构体指针的到地址。
修改一下头插的代码。

//头插
void SListPushFront(SLTNode** pphead, SLTDatatype x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

在这里插入图片描述

尾插

//尾插
void SListPushBack(SLTNode** pphead, SLTDatatype x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	//链表为空
	//链表不为空
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

看到这里有些人或许又有点不解,为什么这里cur不用二级指针?
在这里插入图片描述
其原因是因为cur访问的结构体里面的内容,并没有要改变指针。
这和上面的一定要做区分

头删

//头删
void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	//检查链表是否为空
	assert(*pphead);

	SLTNode* del = *pphead;
	*pphead = (*pphead)->next;
	free(del);
	del = NULL;

}

尾删

//尾删
void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	//方法1
	//if ((*pphead)->next == NULL)
	//{
	//	free(*pphead);
	//	*pphead = NULL;
	//}
	//else
	//{
	//	SLTNode* del = *pphead;
	//	SLTNode* prev = NULL;

	//	while (del->next != NULL)
	//	{
	//		prev = del;
	//		del = del->next;
	//	}
	//	free(del);
	//	del = NULL;
	//	prev->next = NULL;
	//}

	//法2
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* del = *pphead;
		while (del->next->next != NULL)
		{
			del = del->next;
		}
		free(del->next);
		del->next = NULL;

	}

}

查找

//查找
SLTNode* SListFind(SLTNode* phead, SLTDatatype x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

在pos位置之后插入

//在pos位置之后插入
void SListInsertAfter(SLTNode* pos, SLTDatatype x)
{

	assert(pos);
	SLTNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;

}

在pos位置之前插入

//在pos位置之前插入
void SListInsertBefor(SLTNode** pphead, SLTNode* pos, SLTDatatype x)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SLTNode* newnode = BuySListNode(x);
		//寻找pos之前位置
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		newnode->next = pos;
		prev->next = newnode;
	}

}

删除pos位置之后的值

//删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{
	assert(pos);
	if (pos->next == NULL)
	{
		return;
	}
	else
	{
		SLTNode* del = pos->next;
		pos->next = del->next;
		free(del);
	}

}

删除pos位置的值

//删除pos位置的值
void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SListPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

销毁

//销毁
void SListDestory(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

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

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

相关文章

离散数学期末复习第一章 数理逻辑

离散数学 离散数学是研究各种各样的离散量的结构及离散量之间的关系一门学科,是计算机科学中基础理论的核心课程。 什么是连续变量? 在一定区间内可以任意取值的变量叫连续变量,其数值是连续不断的,相邻两个数值可作无限分割&a…

buuctf4

目录 [极客大挑战 2019]LoveSQL [极客大挑战 2019]Http [极客大挑战 2019]Knife qr 镜子里面的世界 ningen 小明的保险箱 爱因斯坦 easycap 隐藏的钥匙 另外一个世界 FLAG [极客大挑战 2019]LoveSQL 1.启动环境, 使用万能密码尝试一下 2.跳转到了check.php…

维度云工业品ERP进销存软件教您如何突破工业品生意的困境?

是困境也是机遇 随着全球化和技术进步的不断推进,工业品贸易正逐渐成为国际贸易的重要组成部分。工业品包含了从原材料、零部件到工业设备、机械以及其他工业用品等范畴的产品,涉及各种制造、加工和组装过程。在全球供应链互联互通之下,工业品…

【人工智能概论】 用Python实现数据的归一化

【人工智能概论】 用Python实现数据的归一化 文章目录 【人工智能概论】 用Python实现数据的归一化一. 数据归一化处理的意义二. 常见的归一化方法2.1 最大最小标准化(Min-Max Normalization)2.2 z-score 标准化 三. 用sklearn实现归一化 一. 数据归一化…

服务(第十一篇)LVS

什么是群集? 多台主机组成的一个整体,提供一个ip访问通道,所有的主机干一件事 提供同样的服务。 群集有哪些类型? ①负载均衡群集(LB): 提高系统的响应能力,处理更多的访问请求&a…

20、Theos越狱调试Wallet

前面的总结中使用砸壳重签后的App进行调试,本篇在越狱环境下不重签App进行调试,但是还是需要砸壳获取Headers. 一、Cycript 1.1 在越狱环境中使用Cycript 在越狱环境上,安装Cycript插件.需要先安装adv-cmds插件,因为被Cycript插件所依赖、在Cydia中,安装Cycript 在设备中找到…

观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色相关图示示例代码框架中的运用适用场景 概念 观察者设计模式(Observer Design Pattern)是一种行为型设计模式,它定义了一种对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当…

LLaMA模型文件 (搬运工)

LLaMA需要进行申请才能获得官方模型权重。 但是申请的审批时间一般都很长。 这里提供现有的huggingface上,第三方上传的一些LLaMA模型文件: LLaMA-7BLLaMA-13BLLaMA-7B-hfLLaMA-13B-hf 这里要注意,原始的LLaMA权重文件,是不能…

【Java面试八股文】SSM,SpringBoot篇

引言: 本文对多个平台的面试题进行了汇总、分类、概括、整理,对重点进行了标出,更便于阅读和记忆。 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 Spring 简单介绍Spri…

ubuntu 20.04 安装obs 录屏软件

obs是一个非常好用的录屏软件,我们在windows安装和使用是非常的简单,但是在ubuntu安装还是比较麻烦的,需要使用命令行,还需要很多的依赖。 修改源 deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multi…

大白话告诉你!前端是怎么回事儿?

假期回家,学会计的表弟化身十万个为什么的问我! 你们前端到底是干什么的?为什么我的同学好多转行去做这个的?你们前端程序员真的这么赚钱么?你也别跟我说什么敲代码的,你告诉我,你敲得这是什么代…

Linux网络——部署YUM仓库

Linux网络——部署YUM仓库 一、YUM仓库服务1.准备安装源:①.软件仓库的提供方式②.RPM软件包的来源③.构建CentOS7软件仓库④.在软件仓库中加入非官方RPM包组⑤.访问yum仓库 2.yum下载软件包的方式①..开启缓存下载②.通过yum命令的选项下载③.通过yumdownloader命令…

容器化实战--vmware安装centos7-安装docker-idea部署springBoot项目到docker

前言 走过的坑终将化为蒲公英,风一吹就消散了,然后继续掉坑… 整体背景 win10 idea2019.3 vmware15 pro CentOS-7-x86_64-DVD-2009.iso docker 23.0.4 redis mysql8 springBoot项目 1.安装虚拟软件vmware15 pro 安装vmware15 2.安装宿主机centos7 …

为什么你永远不应该在CSS中使用px来设置字体大小

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。 在Josh Collinsworth的博客文章“永远不要用px作为字体大小”中,作者讨论了为什么不…

HashMap 的特点及其优缺点以及底层实现

Hash&#xff1a;散列 Map&#xff1a;映射 顾名思义&#xff0c;是以 key-value 的形式存储数据 public class HashMap<K,V> {transient Node<K,V>[] table;// 初始容量 16static final int DEFAULT_INITIAL_CAPACITY 1 << 4; }通过源码可知&#xff0c;…

Web安全 iwebsec 靶场搭建.

Web安全 iwebsec靶场搭建 iwebsec 本质上是一个漏洞集成容器&#xff0c;里面集成了大量的漏洞环境.&#xff08;如&#xff1a;集合了SQL注入、文件包含、命令执行、XXE、反序列化、SSRF、XSS、文件上传等常见的web漏洞环境&#xff09; 目录&#xff1a; 靶场安装步骤&#…

免费gpt-4-国内使用gpt-4

如何用上gpt-4 GPT-4尚未正式发布和公开&#xff0c;因此我们无法提供对GPT-4的具体使用方法。但是&#xff0c;可以从GPT-4的前一代——GPT-3的使用经验和GPT-4的预期功能来看&#xff0c;建议如下&#xff1a; 了解GPT-4的语言处理能力和适用场景&#xff1a;GPT-4预计将进一…

影视动画制作中的后期渲染是什么意思?

影视动画制作是一项非常复杂的任务&#xff0c;需要涵盖从剧本创作到角色设计、场景布置、动画制作、后期渲染等多个环节。其中&#xff0c;后期渲染是制作过程中的最后一步&#xff0c;也是非常重要的一步&#xff0c;它可以使得动画画面更加真实、细腻&#xff0c;达到更好的…

CPU Cache:访问存储速度是如何大幅提升的?

我们了解到不同的物理器件&#xff0c;它们的访问速度是不一样的&#xff1a;速度快的往往代价高、容量小&#xff1b;代价低且容量大的&#xff0c;速度通常比较慢。为了充分发挥各种器件的优点&#xff0c;计算机存储数据的物理器件不会只选择一种&#xff0c;而是以 CPU 为核…

浅析“04.23王者荣耀KPL比赛因出现硬件异常导致比赛延期”这一事件

背景 不知道朋友们有没有看昨天晚上八点多的王者荣耀KPL比赛&#xff08;成都AG超玩会VS广州TTG&#xff09;这一场&#xff0c;当时比赛进行到快15分钟的时候出现了红方请求暂停的情况&#xff0c;后来比赛直播界面就一直提示如下&#xff1a; 本以为这个问题应该不算太严重…