数据结构第三讲:单链表的实现

news2025/2/24 15:15:39

数据结构第三讲:单链表的实现

  • 1.什么是单链表
  • 2. 节点
  • 3.单链表的实现
    • 3.1节点的结构
    • 3.2打印单链表
    • 3.3申请一个新节点
    • 3.4单链表尾部插入
    • 3.5单链表头部插入
    • 3.6单链表的尾部删除
    • 3.7单链表头部删除
    • 3.8查找
    • 3.9在指定位置之前插入数据
    • 3.10在指定位置之后插入数据
    • 3.11删除pos节点
    • 3.12删除pos之后的节点
    • 3.13销毁链表

1.什么是单链表

单链表也是顺序表的一种,它在逻辑结构上是连续的,在物理结构上不一定是连续的

就像是火车一样,有一个火车头、很多节车厢,每相邻的车厢会通过钩子进行链接,单链表中,一节一节的车厢被成为是一个一个的节点,就像这样:
在这里插入图片描述

2. 节点

那么每一个节点到底是怎么样来链接的呢?其实每一个节点中只存储两个数据:需要存储的数据和指向下一个节点的指针,这样通过指针就能够找到下一个节点了

3.单链表的实现

3.1节点的结构

节点只需要存储两个内容,所以实现起来也会比较轻松:

typedef int SLTDateType;

typedef struct SListNode
{
	//存储数据
	SLTDateType date;
	//存储框架
	struct SListNode* next;
}SLTNode;

3.2打印单链表

我们先使用节点结构体自行创建一些节点,然后自行将节点链接起来,如下:

	//通过动态内存分配创建节点
	SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
	node1->date = 1;

	SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
	node2->date = 2;

	SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
	node3->date = 3;

	SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
	node4->date = 4;

	SLTNode* node5 = (SLTNode*)malloc(sizeof(SLTNode));
	node5->date = 5;

	node1->next = node2;
	node2->next = node3;
	node3->next = node4;
	node4->next = node5;
	node5->next = NULL;

然后我们实现一下链表的打印功能:
打印我们使用一个while循环即可,因为链表最后一个节点指向的空间为NULL,所以我们可以以此为一个突破点,作为循环的终止条件,实现如下:

void SLTPrint(SLTNode* phead)
{
	//对于打印,使用一个循环即可
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->date);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

3.3申请一个新节点

上述我们自行申请的一个新节点太过于费事费力了,我们应该试着写一个函数,让函数来帮我们申请空间,实现起来也不困难:

//申请一个新节点
SLTNode* SLBuyNode(SLTDateType x)
{
	SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));

	if (node == NULL)
	{
		perror("malloc faile!");
		exit(1);
	}
	node->date = x;
	node->next = NULL;
	return node;
}

3.4单链表尾部插入

看图:
在这里插入图片描述
我们只需要找到链表的末端,将最后一个节点中的地址指向新的节点,然后将新的节点中的指针指向NULL即可:

//单链表尾部插入
//注意:这里要使用二级指针,因为如果链表中没有节点时,我们要改变头指针的值,让它指向第一个节点的地址
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	//对于插入,首先都要先创建一个节点,才能够实现插入
	SLTNode* newnode = SLBuyNode(x);

	//插入方法
	//1.找到最后一个节点
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* pcur = *pphead;
		while (pcur->next)
		{
			pcur = pcur->next;
		}
		pcur->next = newnode;
	}
}

3.5单链表头部插入

在这里插入图片描述
只需要将刚开辟节点中的指针指向原来的头节点地址,并改变头节点的指向即可:

//单链表头部插入
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	SLTNode* newnode = SLBuyNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}

3.6单链表的尾部删除

在这里插入图片描述
只需要将最后一个节点的空间释放掉,然后将释放后的最后一个节点中的指针指向NULL即可,需要注意的是:这里需要找到释放位置前的节点,当只存在一个节点时,最后一个节点前的空间是不能够进行访问的,这里需要单独讨论:

//单链表尾部删除
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead && *pphead);

	//将只有一个节点的情况单独讨论
	if ((*pphead)->next == NULL)//这里要注意:->的优先级要大于* 所以要将*pphead加上小括号
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		//先找到最后一个数据的前一个数据
		SLTNode* pcur = *pphead;
		SLTNode* prev = NULL;
		while (pcur->next)
		{
			prev = pcur;
			pcur = pcur->next;
		}
		prev->next = NULL;
		free(pcur);
		pcur = NULL;
	}
}

3.7单链表头部删除

在这里插入图片描述
头部删除相对简单,只需要释放空间,然后改变头指针的位置即可:

//单链表头部删除
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && *pphead);

	SLTNode* prev = (*pphead)->next;
	free(*pphead);
	*pphead = prev;
}

3.8查找

查找查找的是数据所在的位置,返回的是节点的地址:

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{
	assert(phead);

	SLTNode* pcur = phead;
	while (pcur)
	{
		if (pcur->date == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

3.9在指定位置之前插入数据

在这里插入图片描述
在指定位置之前插入数据,需要找到指定位置前的那个节点,这里还需要单独讨论,因为当只存在一个节点时,前面的空间是无法访问的,和上边一样,然后我们只需要改变节点中指针的指向即可

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDateType x)
{
	assert(pphead);
	assert(pos);

	//当在第一个节点前进行插入时
	if (*pphead == pos)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		//先创建一个节点
		SLTNode* newnode = SLBuyNode(x);

		SLTNode* pcur = *pphead;
		while (pcur->next != pos)
		{
			pcur = pcur->next;
		}
		pcur->next = newnode;
		newnode->next = pos;
	}
}

3.10在指定位置之后插入数据

在这里插入图片描述
在指定位置之后插入数据,因为已经知道了在哪个位置进行插入,所以我们就能够直接找到下一个节点的地址,直接改变地址指向即可:

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{
	assert(pos);

	//先创建一个节点
	SLTNode* newnode = SLBuyNode(x);

	newnode->next = pos->next;
	pos->next = newnode;
}

3.11删除pos节点

在这里插入图片描述
删除节点,只需要释放空间,改变指针指向即可:

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pos);
	assert(*pphead && pphead);

	if (*pphead == pos)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLTNode* pcur = *pphead;
		while (pcur->next != pos)
		{
			pcur = pcur->next;
		}
		pcur->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

3.12删除pos之后的节点

在这里插入图片描述
释放空间,改变指向:

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);

	pos->next = pos->next->next;
	free(pos->next);
	pos->next = NULL;
}

3.13销毁链表

在这里插入图片描述

使用循环销毁即可:

//销毁链表
void SListDestory(SLTNode** pphead)
{
	assert(pphead && *pphead);

	SLTNode* prew = *pphead;

	while (prew)
	{
		SLTNode* pcur = prew->next;
		free(prew);
		prew = pcur;
	}
	*pphead = NULL;
}

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

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

相关文章

全国区块链职业技能大赛样题第9套前端源码

后端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746050 前端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746216 智能合约+数据库表设计:https://blog.csdn.net/Qhx20040819/article/details/140746646 登录 ​ 用户管理

Java httpclient请求form-data格式,并设置boundary代码实现

文章目录 form-data 数据请求格式样例报错信息: **MissingServletRequestParameterException**解决方法报错信息: **no multipart boundary was found** 解决方法Java代码实现【错误】使用 UrlEncodedFormEntity 、BasicNameValuePair 请求失败(error)【…

【计算机毕业设计】850汽车售后服务信息管理系统

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

《Windows API每日一练》20.1 动态链接库

本节将介绍如何编写动态链接库,并更全面地探讨动态链接库的使用方法,包括以不同的方法装入动态链接库和以不同的方法调用其中的函数等。 本节必须掌握的知识点: 动态链接库的概念 第157练:编写动态链接库DLL 第158练:…

Java从入门到精通(十二)~ 动态代理

晚上好,愿这深深的夜色给你带来安宁,让温馨的夜晚抚平你一天的疲惫,美好的梦想在这个寂静的夜晚悄悄成长。 文章目录 目录 前言 主要作用和功能: 应用场景: 二、代理概念 1.静态代理 2.动态代理 2.1 概念介绍 …

MSPM0G3507将系统时钟改为80M

这款板卡手册上写着最高80M的主频,不过要达到80M需要自己配置时钟树分频倍频。 第一步:打开SysConfig工具,那个方框原本是没有勾选的,这里我们把它勾选 第二步: 点击时钟树配置 第三步: 主要是改变这几个…

nodejs - MongoDB 学习笔记

一、简介 1、MongoDB 是什么 MongoDB 是一个基于分布式文件存储的数据库,官方地址 https://www.mongodb.com/ 2、数据看是什么 数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序。 3、数据库的作用 主要作用是 管理数据…

docker命令大全(新手必备)-my write

一、命令图谱 二、基本命令 docker version #显示版本信息 docker info #显示系统信息,包括镜像、容器数量 docker 命令 --help #帮助 三、镜像命令 3.1 docker images 查看本地主机上的镜像 docker images [OPTIONS] [REPOSITORY[:TAG]] 选项:-a …

【JavaEE初阶】Thread类及常见方法

目录 📕 Thread类的概念 📕 Thread 的常见构造方法 📕 Thread 的几个常见属性 📕 start()-启动一个线程 📕 中断一个线程 🚩 实例一 🚩 实例二 🚩 实例三 📕 jo…

Pytorch深度学习实践(8)多分类任务

多分类问题 多分类问题主要是利用了Softmax分类器,数据集采用MNIST手写数据集 设计方法: 把每一个类别看成一个二分类的问题,分别输出10个概率 但是这种方法存在一种问题:不存在抑制问题,即按照常规来讲&#xff0c…

Python的文件操作介绍

一、编码格式介绍 1.1、常见的字符编码格式 1.2、Python字符编码格式 Python的解释器使用的是Unicode(内存) .py文件在磁盘上使用UTF-8存储(外存) #encodinggbkprint(你好,中国) 二、文件的读写原理 2.1、文件的…

Servlet1-Servlet程序、请求处理、继承体系

目录 什么是Servlet 手动实现Servlet程序 ​编辑url地址如何定位到Servlet程序去访问 Servlet的生命周期 ​编辑GET和POST请求的分发处理 通过继承HttpServlet类实现Servlet程序 IDEA菜单生成Servlet程序 Servlet类的继承体系 ServletConfig类 ServletContext类 什么…

Docker学习与实战

一、Docker安装 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine配置docker yum源 sudo yum install -y yum-utils配置阿里云docker仓库 sudo y…

甄选范文“论软件测试中缺陷管理及其应用”软考高级论文,系统架构设计师论文

论文真题 软件缺陷指的是计算机软件或程序中存在的某种破坏正常运行能力的问题、错误,或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。在目前的软件开发过程中,缺陷是不可避免的。软件测试是发现缺陷的主要手段,其核心目标就是尽可能多地找…

Nvidia GPU驱动安装报错显卡与驱动不兼容(本身兼容)

最近在公司服务器上遇到了一个特别离谱的问题,就是在本身在nividia官网上面下载的匹配的显卡驱动,安装之后采用下面命令查看驱动显示: $ nvidia-smiNVIDIA-SMI has failed because it couldnt communicate with the NVIDIA driver. Make su…

exe4j 使用jar包 打包exe程序,并且自带jre

1. 准备工作 1) 程序jar包一个 2) jdk自带jre文件夹一个 3)exe4j 程序 ,自行搜索 我用的5.1 4)图标(icon)文件一个,用来作为exe程序的图标 5) 图片(png/jpg等)用来打开…

LeetCode 118.杨辉三角 C++写法

LeetCode 118.杨辉三角 C写法 思路🧐: 我们使用vector来进行解答,该题规律简单,观察一下就可以发现,下一行的非1部分是上一行相同下标与上一行相同下标的前一个数据的和。难一点的是数据存储方式,C语言需要…

相机怎么选(不推荐,只分析)

title: 相机怎么选 tags: [相机, 单反相机] categories: [其他, 相机] 最近准备购买,相机怎么选,我去搜索了许多文章,整理了一篇小白挑选技术篇,供大家参考。 分类 胶片相机 需要装入胶卷才能使用的相机,拍照后可直…

【网络安全】子域名模糊测试实现RCE

未经许可,不得转载。 文章目录 正文总结 正文 在之前测试一个私人项目时,我报告了admin.Target.com上的Auth Bypass漏洞,这将导致SQLI&RCE ,该漏洞在报告后仅一天就被修复。 现在重拾该应用程序,对子域进行模糊测…

安德森四原则:从对称性破缺到复杂性涌现

中国物理学会期刊网 2023年06月20日 10:00 北京 以下文章来源于集智俱乐部,作者 Krakauer 导语 对称性破缺与复杂性的涌现有何关系?在几十年的研究进程中,诺奖得主、圣塔菲研究所发起人菲利普安德森(Philip Anderson&#xff09…