单链表操作

单链表操作

  • 1. 链表的概念
  • 2. 链表的分类
    • 2.1.单向或者双向
    • 2.2 带头或者不带头
    • 2.3 循环或者非循环
    • 2.4 常用的链表
  • 3. 单链表的实现
    • 3.1 单链表的打印
    • 3.2 单链表的头插
    • 3.3 单链表的尾插
    • 3.4 单链表的头删
    • 3.5 单链表的尾删
    • 3.6 单链表的查询
    • 3.7 在pos前插入数据
    • 3.8 在pos后插入数据
    • 3.9 删除pos位置数据
    • 3.10 删除pos位置后的数据

1. 链表的概念

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

2. 链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

2.1.单向或者双向

单向或者双向链表

2.2 带头或者不带头

带头或者不带头链表

2.3 循环或者非循环

循环或者非循环链表

2.4 常用的链表

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:
在这里插入图片描述

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

3. 单链表的实现

以上有这么多种类的链表,我们这里来实现单链表的操作:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLTDataType;
//定义一个结构体
typedef struct SListNode
{
	SLTDataType data;//数据域
	struct SListNode* next;//指针域
}SLTNode;

//单链表的打印
void SLTPrint(SLTNode* phead);
//单链表的头插
void SLPushFront(SLTNode** pphead,SLTDataType x);
//单链表的尾插
void SLPushBack(SLTNode** pphead, SLTDataType x);
//单链表的头删
void SLPopFront(SLTNode** pphead);
//单链表的尾删
void SLPopBack(SLTNode** pphead);
//单链表的查询
SLTNode* STFind(SLTNode* phead,SLTDataType x);

//在pos前插入数据
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos后插入数据
void SLInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置数据
void SLErase(SLTNode** pphead, SLTNode* pos);
//删除pos位置后的数据
void SLEraseAfter(SLTNode** pphead, SLTNode* pos);

3.1 单链表的打印

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

cur指针指向头结点,令cur->next走起来并打印data,直到cur->next指向空指针。

3.2 单链表的头插

SLTNode* BuyLTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void SLPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuyLTNode(x);

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

因为插入时我们要先创建一个新的结点,为了减少代码的冗余,我们直接写了一个函数*BuyLTNode()*来创建新的结点。这里传参传的是二级指针,因为我们要改变的是头指针(本来头指针指向空,我们现在尾插了一个新结点,让头指针指向新结点),改变指针,我们就传指针的地址,所以用二级指针来接受。

3.3 单链表的尾插

void SLPushBack(SLTNode** pphead, SLTDataType x)
{
   	
	SLTNode* newnode = BuyLTNode(x);
	//空链表
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	//非空链表
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

头插时应当判断链表是否为空。

3.4 单链表的头删

void SLPopFront(SLTNode** pphead)
{
	assert(pphead);
	//没有节点
	assert(*pphead);
	/*if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else 
	{*/
		SLTNode* del = *pphead;
		*pphead = del->next;
		free(del);
	//}
}

头删如果没有结点,我们直接报出错误。

3.5 单链表的尾删

void SLPopBack(SLTNode** pphead)
{
	//没有节点
	assert(*pphead);
	/*if (*pphead == NULL)
	{
		return;
	}*/

	//一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		/*SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next)
		{
			prev = tail;
			tail = tail->next;

		}
		free(tail);
		prev->next = NULL;*/


		SLTNode* tail = *pphead;
		while (tail->next->next)
		{
			tail = tail->next;

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

	}
}

尾删也一样,没有结点直接报错,有一个直接将头结点置为空。

3.6 单链表的查询

SLTNode* STFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

查询没什么好说的,从头开始一个一个遍历,找到返回该指针,找不到返回空。

3.7 在pos前插入数据

void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);

	if (*pphead == pos)
	{
		SLPushFront(pphead, x);
	}
	else 
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuyLTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

在pos前插入数据需要判断一下是否头指针指向的结构体是你需要插入的,如果是,直接头插。

3.8 在pos后插入数据

void SLInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);

	SLTNode* newnode = BuyLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

在pos前插入数据就没必要需要判断一下是否头指针指向的结构体是你需要插入的,即使是,也直接插入就行了。

3.9 删除pos位置数据

void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

删除pos位置数据需要判断头是否是你要删除的,如果是,直接头删。

3.10 删除pos位置后的数据

void SLEraseAfter(SLTNode** pphead, SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* after=pos->next;
	pos->next = pos->next->next;
	free(after);
	
}

删除pos位置后的数据也就不需要判断头是否是你要删除的了。

代码参考: https://gitee.com/yujin518/test_c/tree/master/test_3_13

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

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

相关文章

Linux——进程通信(一) 匿名管道

目录 前言 一、进程间通信 二、匿名管道的概念 三、匿名管道的代码实现 四、管道的四种情况 1.管道无数据&#xff0c;读端需等待 2.管道被写满&#xff0c;写端需等待 3.写端关闭&#xff0c;读端一直读取 4.读端关闭&#xff0c;写端一直写入 五、管道的特性 前言 …

不锈钢多功能电工剥线钳分线绕线剪线剥线钳剥线压线扒皮钳子

品牌&#xff1a;银隆 型号&#xff1a;089B绿色 材质&#xff1a;镍铬钢&#xff08;不锈钢&#xff09; 颜色分类&#xff1a;089B灰色,089B红色,089B绿色,089B黑色,089B橙色 功能齐集一身&#xff0c;一钳多用&#xff0c;多功能剥线钳。剥线&#xff0c;剪线&#xff…

Java-CAS 原理与 JUC 原子类

由于 JVM 的 synchronized 重量级锁涉及到操作系统&#xff08;如 Linux&#xff09; 内核态下的互斥锁&#xff08;Mutex&#xff09;的使用&#xff0c; 其线程阻塞和唤醒都涉及到进程在用户态和到内核态频繁切换&#xff0c; 导致重量级锁开销大、性能低。 而 JVM 的 synchr…

免费阅读篇 | 芒果YOLOv8改进114:上采样Dysample:顶会ICCV2023,轻量级图像增采样器,通过学习采样来学习上采样,计算资源需求小

&#x1f4a1;&#x1f680;&#x1f680;&#x1f680;本博客 改进源代码改进 适用于 YOLOv8 按步骤操作运行改进后的代码即可 该专栏完整目录链接&#xff1a; 芒果YOLOv8深度改进教程 &#x1f680;&#x1f680;&#x1f680; DySample是一个超轻量级和有效的动态上采样器…

DDos攻击如何被高防服务器有效防范?

德迅云安全-领先云安全服务与解决方案提供商 什么是DDos攻击&#xff1f; DDos攻击是一种网络攻击手段&#xff0c;旨在通过使目标系统的服务不可用或中断&#xff0c;导致无法正常使用网络服务。DDos攻击可以采取多种方式实施&#xff0c;包括洪水攻击、压力测试、UDP Flood…

HTML静态网页成品作业(HTML+CSS)——游戏战地介绍设计制作(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有4个页面。 二、作品演示 三、代…

关于PXIE3U18槽背板原理拓扑关系

如今IT行业日新月异&#xff0c;飞速发展&#xff0c;随之带来的是数据吞吐量的急剧升高。大数据&#xff0c;大存储将成为未来数据通信的主流&#xff0c;建立快速、大容量的数据传输通道将成为电子系统的关键。随着集成技术和互连技术的发展&#xff0c;新的串口技术&#xf…

【QT+QGIS跨平台编译】之七十七:【QGIS_Gui跨平台编译】—【错误处理:字符串错误】

文章目录 一、字符串错误二、处理方法三、涉及到的文件一、字符串错误 常量中有换行符错误:(也有const char * 到 LPCWSTR 转换的错误) 二、处理方法 需要把对应的文档用记事本打开,另存为 “带有BOM的UTF-8” 三、涉及到的文件 src\gui\qgsadvanceddigitizingdockwidge…

ClickHouse中的设置的分类

ClickHouse中的各种设置 ClickHouse中的设置有几百个&#xff0c;下面对这些设置做了一个简单的分类。

【Godot 4.2】常见几何图形、网格、刻度线点求取函数及原理总结

概述 本篇为ShapePoints静态函数库的补充和辅助文档。ShapePoints函数库是一个用于生成常见几何图形顶点数据&#xff08;PackedVector2Array&#xff09;的静态函数库。生成的数据可用于_draw和Line2D、Polygon2D等进行绘制和显示。因为不断地持续扩展&#xff0c;ShapePoint…

Orbit 使用指南 03 | 与刚体交互 | Isaac Sim | Omniverse

如是我闻&#xff1a; “在之前的指南中&#xff0c;我们讨论了独立脚本&#xff08; standalone script&#xff09;的基本工作原理以及如何在模拟器中生成不同的对象&#xff08;prims&#xff09;。在指南03中&#xff0c;我们将展示如何创建并与刚体进行交互。为此&#xf…

机器学习周记(第三十周:文献阅读-SageFormer)2024.3.11~2024.3.17

目录 摘要 ABSTRACT 1 论文信息 1.1 论文标题 1.2 论文摘要 1.3 论文背景 2 论文模型 2.1 问题描述 2.2 模型信息 2.2.1 Series-aware Global Tokens&#xff08;序列感知全局标记&#xff09; 2.2.2 Graph Structure Learning&#xff08;图结构学习&#xff09; …

大数据面试题之SQL题

大数据面试题之SQL题 1.有一个录取学生人数表&#xff0c;记录的是每年录取学生人数和入学学生的学制 以下是表结构&#xff1a; CREATE TABLE admit ( id int(11) NOT NULL AUTO_INCREMENT, year int(255) DEFAULT NULL COMMENT ‘入学年度’, num int(255) DEFAULT NULL COMM…

交流互动系统|基于springboot框架+ Mysql+Java+Tomcat的交流互动系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

【医学图像处理】ECAT和HRRT格式转nii格式【超简单】

之前从ADNI上下载PET数据的时候发现有许多数据的格式不是DICOM的而是ECAT或者是HRRT格式&#xff0c;这对原本就少的PET数据是血上加霜啊。 当然只使用DICOM格式的数据也会得到不少的数据&#xff0c;我一开始也是只使用DICOM格式的样本&#xff0c;后来为了得到更多的数据&a…

2024年值得创作者关注的十大AI动画创新平台

别提找大型工作室制作动画了。如今,AI平台让我们就可以轻松制作动画。从简单的文本生动画功能到复杂的角色动作,这些平台为各种类型的创作者提供了不同的功能。 AI已经有了长足的发展,现在它可以理解复杂的人类动作和艺术意图,将简单的输入转化成丰富而详细的动画。 下面…

RoketMQ主从搭建

vim /etc/hosts# IP与域名映射&#xff0c;端口看自己的#nameserver 192.168.126.132 rocketmq-nameserver1 192.168.126.133 rocketmq-nameserver2# 注意主从节点不在同一个主机上 #broker 192.168.126.132 rocketmq-master1 192.168.126.133 rocketmq-master2#broker 192.168…

HarmonyOS(鸿蒙)不再适合JS语言开发

ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风格的基础上&#xff0c;对TS的动态类型特性施加更严格的约束&#xff0c;引入静态类型。同时&#xff0c;提供了声明式UI、状态管理等相应的能力&#xff0c;让开发者可以以更简洁、…

用Python 3 开发的摄像头拍照程序

在当今数字化的世界中&#xff0c;使用摄像头进行拍照已成为日常生活的重要组成部分。无论是用于个人用途还是专业用途&#xff0c;能够使用电脑摄像头轻松拍照都是一项有用的技能。本文将指导您使用 Python 3 编写一个简单的程序&#xff0c;让您能够使用电脑摄像头拍照并将其…

如果网络不好 如何下载huggingface上的模型

很多朋友网络不太好&#xff0c;有时候上不了huggingface这样的国外网站&#xff1b; 或者网络流量不太够&#xff0c;想要下载一些stable diffusion模型&#xff0c;或者其他人工智能的大模型的时候&#xff0c;看到动辄几个G的模型文件&#xff0c;不太舍得下载&#xff1b;…