【数据结构 04】单链表

一、链表简介

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

链表在结构上的分类

1. 带头结点或无头结点
2. 单向或双向
3. 循环或非循环

虽然链表有多种结构类型,但是我么在实际开发中常用的只有两种结构:

  1. 无头单向非循环链表:结构简单,通常不单独使用,而是作为其他数据结构的子结构,如哈希桶、图的邻接表……
  2. 带头双向循环链表:结构最复杂,功能最全面,使用效率高

下例代码是无头单向非循环链表的实现,设计思路:

  1. 每个ListNode节点都包含一个数据和一个next指针,next指针指向下一个节点
  2. 当pList == NULL 的时候,代表这个链表为空,没有任何数据
  3. 链表最后一个节点的next指针一定是NULL
  4. 当函数涉及数据增删时,传入的参数为二级指针 ListNode** ppList

二、SingleList.h

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

typedef int DataType;

typedef struct ListNode
{
	DataType data;
	struct ListNode* next;
}ListNode;

bool Empty(ListNode* plist)
{
	return plist == NULL;
}

void Print(ListNode* plist)
{
	ListNode* cur = plist;
	while (cur != NULL)
	{
		printf("%2d -> ", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

// 动态申请一个节点
ListNode* BuyNode(DataType x)
{
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	node->data = x;
	node->next = NULL;
	return node;
}

// 尾插
void PushBack(ListNode** pplist, DataType x)
{
	assert(pplist);
	ListNode* node = BuyNode(x);

	// 插入链表的第一个节点
	if (*pplist == NULL)
	{
		*pplist = node;
		return;
	}

	// cur指针通过循环遍历找到链表的尾结点
	ListNode* cur = *pplist;
	while (cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = node;
}

// 头插
void PushFront(ListNode** pplist, DataType x)
{
	assert(pplist);
	ListNode* node = BuyNode(x);

	if (*pplist == NULL)
	{
		*pplist = node;
		return;
	}

	node->next = *pplist;
	*pplist = node;
}

// 尾删
void PopBack(ListNode** pplist)
{
	if (Empty(*pplist))
	{
		printf("链表为空,尾删失败\n");
		return;
	}

	ListNode* cur = *pplist;
	ListNode* prev = cur;
	while (cur->next != NULL)
	{
		prev = cur;
		cur = cur->next;
	}
	free(cur);
	cur = NULL;
	prev->next = NULL;
}

// 头删
void PopFront(ListNode** pplist)
{
	if (Empty(*pplist))
	{
		printf("链表为空,尾删失败\n");
		return;
	}

	ListNode* cur = *pplist;
	*pplist = cur->next;
	free(cur);
	cur = NULL;
}

// 查找,返回第一个元素x的节点
ListNode* Find(ListNode* plist, DataType x)
{
	ListNode* cur = plist;
	while (cur != NULL)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

// 在pos后面插入新节点,pos节点由Find函数获得
void InsertAfter(ListNode* pos, DataType x)
{
	if (pos == NULL)
	{
		printf("pos为空,数据插入失败\n");
		return;
	}
	ListNode* node = BuyNode(x);
	node->next = pos->next;
	pos->next = node;
}

// 删除pos节点
void Delete(ListNode** pplist, ListNode* pos)
{
	if (pos == NULL)
	{
		printf("pos为空,数据删除失败\n");
		return;
	}
	if (Empty(*pplist))
	{
		printf("单链表已为空,Delete失败\n");
		return;
	}

	ListNode* cur = *pplist;
	ListNode* prev = NULL;
	while (cur)
	{
		if (cur->data == pos->data && prev == NULL)
		{
			// 删除第一个节点
			*pplist = pos->next;
			free(pos);
			pos = NULL;
			return;
		}
		if (cur->data == pos->data)
		{
			prev->next = pos->next;
			free(pos);
			pos = NULL;
			return;
		}

		prev = cur;
		cur = cur->next;
	}
}

// 销毁链表
void Destroy(ListNode** pplist)
{
	while (*pplist)
	{
		ListNode* cur = *pplist;
		*pplist = cur->next;
		free(cur);
		cur = NULL;
	}
	printf("链表销毁成功\n");
}

三、test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "SingleList.h"

int main()
{
	ListNode* plist = NULL;

	// 尾插数据
	PushBack(&plist, 1);
	PushBack(&plist, 3);
	PushBack(&plist, 5);
	PushBack(&plist, 7);
	Print(plist);

	// 头插数据
	PushFront(&plist, 2);
	PushFront(&plist, 4);
	PushFront(&plist, 6);
	PushFront(&plist, 8);
	Print(plist);

	// 尾删数据
	PopBack(&plist);
	PopBack(&plist);
	PopBack(&plist);
	Print(plist);

	// 头删数据
	PopFront(&plist);
	PopFront(&plist);
	PopFront(&plist);
	Print(plist);

	// 在查找的元素后面插入节点
	InsertAfter(Find(plist, 1), -1);
	InsertAfter(Find(plist, 2), -2);
	InsertAfter(Find(plist, -2), 22);
	Print(plist);

	// 删除查找到的节点
	Delete(&plist, Find(plist, -2));
	Delete(&plist, Find(plist, -1));
	Delete(&plist, Find(plist, 22));
	Delete(&plist, Find(plist, 100)); // pos为空,数据删除失败!
	Print(plist);

	// Delete删空链表
	Delete(&plist, Find(plist, 2));
	Delete(&plist, Find(plist, 1));
	Delete(&plist, Find(plist, 1)); // pos为空,数据删除失败!
	Print(plist);

	// 销毁链表,先插入数据测试
	PushBack(&plist, 1);
	PushBack(&plist, 2);
	PushBack(&plist, 3);
	Print(plist); // 1 -> 2 -> 3 -> NULL
	Destroy(&plist); // 链表销毁成功
	Print(plist);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

云计算概述(云计算类型、技术驱动力、关键技术、特征、特点、通用点、架构层次)(二)

云计算概述&#xff08;二&#xff09; &#xff08;云计算类型、技术驱动力、关键技术、特征、特点、通用点、架构层次&#xff09; 目录 零、00时光宝盒 一、云计算类型&#xff08;以服务的内容或形态来分) 二、云计算的12种技术驱动力 三、云计算的关键技术 四、云计…

软件工程知识梳理4-详细设计

详细设计阶段的根本目标是确定应该怎样具体地实现所要求的系统&#xff0c;也就是说.经过这个阶段的设计工作.应该得出对目标系统的精确描述.从而在编码阶段可以把这个描述直接翻译成用某种程序设计语言书写的程序。 详细设计的的目标不仅仅是逻辑上正确地实现每个模块地功能&a…

ONLYOFFICE 文档 8.0 现已发布:PDF 表单、RTL、单变量求解、图表向导、插件界面设计等更新

我们最新版本的在线编辑器现已推出&#xff0c;为整个套件优化了多项功能。阅读下文&#xff0c;了解详细更新内容。 什么是 ONLYOFFICE 文档 ONLYOFFICE 文档是一款开源的办公套件&#xff0c;由总部位于拉脱维亚的Ascensio System SIA开发。它支持处理文本文档、电子表格、演…

【ASP.NET Core 基础知识】--Web API--创建和配置Web API(一)

一、简介 Web API&#xff08;Web Application Programming Interface&#xff09;的重要性在于其在现代软件开发中扮演着关键的角色。以下是一些关于Web API重要性的方面&#xff1a; 跨平台交互&#xff1a; Web API允许不同平台、不同技术栈的应用程序进行通信。无论是Web…

有可能通过打印机墨盒入侵电脑吗?

&#x1f5a8; 有可能通过打印机墨盒入侵电脑吗&#xff1f; HP 公司首席执行官 Enrique Lores 在接受 CNBC 采访时说&#xff0c;不能使用非原装打印机墨盒。否则&#xff0c;打印将被阻止。 对于这一决定&#xff0c; Lores 给出了两个理由。首先&#xff0c;非原装墨盒可能…

npm淘宝镜像过期解决办法

npm淘宝镜像过期解决办法 因为npm 官方镜像&#xff08;registry.npmjs.org&#xff09;在国内访问很慢&#xff0c;我们基本上都会选择切换到国内的一些 npm 镜像&#xff08;淘宝镜像、腾讯云镜像等&#xff09;。由于淘宝原来的镜像&#xff08;registry.npm.taobao.org&am…

Mac 终端可以使用yarn,但是vscode里面报错segmentation fault

Mac 终端可以使用yarn 但是vscode里面报错segmentation fault 查阅官网https://www.yarnpkg.cn/getting-started/install 在vscode运行corepack enable即可解决该问题

【golang】13、viper 配置库 | 配置文件读写 | 使用方式 | 源码逻辑分析

文章目录 一、使用方式1.1 特性1.2 优势1.3 设置1.3.1 默认值1.3.2 配置文件1.3.3 写配置文件1.3.4 监听配置文件变化1.3.5 从 io.Reader 读配置1.3.6 Setting Overrides1.3.7 使用 Alias1.3.8 环境变量1.3.9 命令行 Flags1.3.8.1 Flag 接口 1.3.9 配置中心1.3.9.1 未加密1.3.9…

NoSQL数据库简介

NoSQL数据库简介 Brief Introduction to NoSQL Databases By JacksonML 1. 什么是SQL&#xff1f; 在了解NoSQL之前&#xff0c;先简要介绍一下SQL。 SQL是 Structured Query Language&#xff08;结构化查询语言&#xff09;的缩写。 SQL在关系型数据中广泛使用&#xf…

Linux中vim编辑器的使用

vim常见使用方法 vim介绍命令模式下常用命令用法底行模式下常见命令用法注释代码删除 vim细节vim的配置问题 vim介绍 vim是一款多模式的编辑器 所谓多模式就是有几种模式供我们选择使用 创建一个文件叫test.c&#xff0c;用vim打开就是 vim test.c这样就可以打开test.c进行编…

运维SRE-04 磁盘管理体系

磁盘管理体系详解 磁盘管理系统概述 目标 熟练掌握常用磁盘配置(容量,转速,个数)熟练说出来或写出来: raid级别熟练掌握磁盘基础使用:拿到一块硬盘到可以向硬盘写入数据分区,格式化,挂载熟练掌握: 磁盘空间不足 no space left on device 故障,原因,排查,解决. 磁盘基础内容 …

17.Golang channel的基本定义及使用

目录 概述实践无缓冲 channel代码结果 缓冲 channel代码结果 channel的关闭特点代码结果range代码结果 select channel代码结果 结束 概述 此篇文章介绍 channel 的用法 无缓冲 channel缓冲 channelchannel的关闭特点range channelselect channel 每一种&#xff0c;配上完整…

深入浅出AI落地应用分析:AI个人助手Monica

前言:铺天盖地的大模型以及所谓的应用到目前为止实际还是很少有像Monica这样贴合个人工作习惯的产品落地,比如像Chatgpt等这样的产品,绝大多数人不会专门买🪜翻墙出去用,而且大多数场景下素人或小白都不知道该怎么用,但是Monica这款产品就很好的以浏览器的插件的形式始终…

29 python快速上手

Python操作MySQL和实战 1. 事务1.1 MySQL客户端1.2 Python代码 2. 锁2.1 排它锁2.2 共享锁 3. 数据库连接池4. SQL工具类4.1 单例和方法4.2 上下文管理 5.其他总结 目标&#xff1a;掌握事务和锁以及Python操作MySQL的各种开发必备知识。 概要&#xff1a; 事务锁数据库连接池…

【Oracle云】使用 boto3 访问 OCI 对象存储 (AWS S3协议兼容)

在现代云计算环境中&#xff0c;S3&#xff08;Simple Storage Service&#xff09;协议已经成为云对象存储的事实标准。它提供了简单、可扩展、高度耐用的存储解决方案&#xff0c;得到了广泛应用。Oracle Cloud Infrastructure&#xff08;OCI&#xff09;秉承着开放性和灵活…

摄像头监控系统/视频监控云平台EasyCVR接入单兵设备后如何配置移动规矩

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体控可实现视频监控直播、视频轮播、视频录像…

Java编程练习之类的封装

1.把一个Student类封装起来&#xff0c;模拟一个转校生转入新学校后为其制作学生信息的过程。运行结果如下&#xff1a; package zhtestdemo; import java.util.Scanner; import java.text.DecimalFormat; public class demo { //创建类&#xff0c;类名叫demo; private Stud…

CentOS7中安装ElasticSearch

文章目录 检测是否安装了Elasticsearch安装JDK下载java配置 下载Elasticsearch解压安装Elasticsearch修改配置文件启动Elasticsearch常见问题 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasti…

【Ubuntu 18.04 安装截图软件 flameshot 】

安装命令&#xff1a; sudo apt-get install flameshot 使用命令&#xff1a; flameshot gui 创建快捷键&#xff1a;设备->键盘->>输入名字和快捷键 截完图后保存CtrlS&#xff0c;复制到剪贴板 CtrlC ​​​​​​

Altium Designer的学习

PCB设计流程 1.新建空白工程&#xff1a; 创建一个新的工程 新建四个文件&#xff0c;并且保存&#xff1a; 每次打开文件时&#xff0c;打开以.PrjPcb结尾的文件 2.元件符号的创建&#xff1a; 在绘制图形的时候设置成10mil,为了在原理图中显得不那么大。 在绘制引脚的时候设…