当前位置: 首页 > news >正文

[数据结构]无头单向非循环链表的实现与应用

文章目录

  • 一、引言
  • 二、线性表的基本概念
    • 1、线性表是什么
    • 2、链表与顺序表的区别
    • 3、无头单向非循环链表
  • 三、无头单向非循环链表的实现
    • 1、结构体定义
    • 2、初始化
    • 3、销毁
    • 4、显示
    • 5、增删查改
  • 四、分析无头单向非循环链表
    • 1、存储方式
    • 2、优点
    • 3、缺点
  • 五、总结
    • 1、练习题
    • 2、源代码

一、引言

在踏入编程的奇幻世界时,我们常常会遇到各种奇妙的数据结构,它们如同搭建宏伟城堡的砖石,不可或缺。而要想深入理解无头单向非循环链表这一复杂而强大的数据结构,首先得从它的基石 —— 线性表的基本概念开始。本文将分为两大篇章,第一篇章将带你漫步于线性表的瑰丽花园,探索其本质与奥秘;第二篇章则将引领你穿越无头单向非循环链表的迷雾,领略其实现与应用的壮丽风景。

对于指针和数组还感到迷茫的朋友,这里有一个精心准备的传送门,它将是你探索这些基石概念的得力助手。请放心,一旦你掌握了这些基础知识,无头单向非循环链表的神秘面纱将不再难以揭开。


二、线性表的基本概念

1、线性表是什么

想象一下,你手中握着一串璀璨的珍珠项链,每一颗珍珠都紧紧相连,形成一个有序的整体。这就是线性表的生动写照。线性表,简单来说,就是一系列具有相同特性的数据元素的有限序列,它们之间存在着一对一的相邻关系,如同项链上的珍珠,一个接一个,既独立又紧密相连。

2、链表与顺序表的区别

线性表有两种基本的存储结构:链表和顺序表。顺序表,就像是一个排列整齐的书架,每个位置都预先分配好了,书籍(数据元素)按照顺序摆放。而链表,则更像是那条珍珠项链,每颗珍珠(数据元素)都通过一根无形的线(指针)与下一颗珍珠相连,形成了一条灵活的链条。链表允许在任意位置添加或删除元素,而无需移动其他元素,这正是其独特魅力所在。

3、无头单向非循环链表

在无头单向非循环链表中,我们没有那颗象征起点的 “头珍珠” ,也没有形成一个闭环的链条。每个节点都只知道如何找到它的下一个节点(如果存在的话),但不知道整个链条的起点或终点在哪里。这种结构简洁而灵活,非常适合用于需要频繁添加或删除元素的场景。

请添加图片描述


三、无头单向非循环链表的实现

1、结构体定义

首先,我们需要定义一个结构体来表示链表中的每一个节点。这个结构体通常包含两个部分:一是存储数据元素的数据域;二是指向下一个节点的指针域。

typedef int DataType;typedef struct SListNode {DataType data;//数据域struct SListNode* next;//指针域
}SL;

2、初始化

创建一个无头单向非循环链表,首先需要初始化这个链表,即创建第一个节点,并让它指向NULL。

void Init(SL** head, DataType data)
{assert(head != NULL && *head == NULL);SL* pos = (SL*)malloc(sizeof(SL));if (pos == NULL){fprintf(stderr, "内存分配失败");exit(EXIT_FAILURE);}pos->data = data;pos->next = *head;(*head) = pos;
}

3、销毁

当链表不再需要时,我们应该及时释放它所占用的内存资源。遍历链表,逐一释放每个节点的内存,最后将头指针也置为NULL。

void Destory(SL** head)
{if (head == NULL)return;while (*head != NULL){SL* next = (*head)->next;free(*head);*head = next;}*head = NULL;
}

4、显示

为了查看链表中的元素,我们需要遍历链表,并依次打印出每个节点的数据域。

void Print(SL** head, void (*Prin) (DataType))
{assert(head != NULL && Prin != NULL);for (SL* i = *head; i != NULL; i = i->next){Prin(i->data);}printf("NULL\n");
}

5、增删查改

链表的核心操作包括增加、删除、查找和修改节点。这些操作都需要我们灵活运用指针来定位、修改或删除链表中的节点。

void PushFront(SL** head, DataType data)
{assert(head != NULL);SL* pos = (SL*)malloc(sizeof(SL));if (pos == NULL){fprintf(stderr, "内存分配失败");exit(EXIT_FAILURE);}pos->data = data;pos->next = *head;*head = pos;
}void PopFront(SL** head)
{assert(head != NULL && *head != NULL);SL* next = (*head)->next;free(*head);*head = next;
}void PushBack(SL** head, DataType data)
{Insert(head, NULL, data);
}void PopBack(SL** head)
{assert(head != NULL && *head != NULL);for (SL* i = *head; i->next != NULL; i = i->next){if (i->next->next == NULL){free(i->next);i->next = NULL;return;}}
}void Insert(SL** head, SL* x, DataType data)
{assert(head != NULL);if (*head == x){PushFront(head, data);}for (SL* i = *head; i != NULL; i = i->next){if (i->next == x){SL* pos = (SL*)malloc(sizeof(SL));if (pos == NULL){fprintf(stderr, "内存分配失败");exit(EXIT_FAILURE);}pos->data = data;pos->next = i->next;i->next = pos;return;}}assert(0);
}void Erase(SL** head, SL* x)
{assert(head != NULL && *head != NULL && x != NULL);if (*head == x){PopFront(head);}for (SL* i = *head; i != NULL; i = i->next){if (i->next == x){i->next = x->next;free(x);return;}}assert(0);
}SL* Find(SL** head, DataType data)
{assert(head != NULL && *head != NULL);for (SL* i = *head; i != NULL; i = i->next){if (i->data == data)return i;}return NULL;
}void Modify(SL** head, SL* x, DataType data)
{assert(head != NULL && x != NULL);for (SL* i = *head; i != NULL; i = i->next){if (i == x){i->data = data;return;}}assert(0);
}

四、分析无头单向非循环链表

1、存储方式

无头单向非循环链表采用动态分配内存的方式来存储节点,每个节点只保存指向下一个节点的指针。这种存储方式使得链表能够灵活地应对元素数量的变化。

2、优点

  • 无需预先分配固定大小的存储空间,能够根据需要动态地增加或减少节点。
  • 插入和删除操作的时间复杂度较低,特别是在链表中间或尾部进行操作时。

3、缺点

  • 访问链表中任意位置的元素需要从头开始遍历,因此时间复杂度较高。
  • 链表的每个节点都需要额外的指针域来存储指向下一个节点的指针,这会增加一定的内存开销。

五、总结

1、练习题

  • 分割链表
  • 环形链表的约瑟夫问题
  • 反转链表
  • 链表的中间节点
  • 合并两个有序链表
  • 移除链表元素
  • 回文链表

2、源代码

对于无头单向非循环链表的源代码我已经开源在GItee:传送门


相关文章:

[数据结构]无头单向非循环链表的实现与应用

文章目录 一、引言二、线性表的基本概念1、线性表是什么2、链表与顺序表的区别3、无头单向非循环链表 三、无头单向非循环链表的实现1、结构体定义2、初始化3、销毁4、显示5、增删查改 四、分析无头单向非循环链表1、存储方式2、优点3、缺点 五、总结1、练习题2、源代码 一、引…...

认识结构体

目录 一.结构体类型的声明 1.结构的声明 2.定义结构体变量 3.结构体变量初始化 4.结构体的特殊声明 二.结构体对齐(重点难点) 1.结构体对齐规则 2.结构体对齐练习 (一)简单结构体对齐 (二)嵌套结构体对齐 3.为什么存在内存对齐 4.修改默认对齐数 三.结构体传参 1…...

Linux驱动.之MT7601,USB-WiFi网卡移植到X210开发板,wpa_supplicant配置工具的使用(一)

一、移植前 1、下载与解压无线网卡MT7601U驱动源码压缩包 DPO_MT7601U_LinuxSTA_3.0.0.4_20130913.tar.bz2 解压后有如下文件 ate common iwpriv_usage.txt Makefile mgmt phy README_STA_usb RT2870STA.dat sta_ate_iwpriv_usage.txt chips include m…...

ChatGPT 在国内使用的方法

AI如今很强大,聊聊天、写论文、搞翻译、写代码、写文案、审合同等等,ChatGPT 真是无所不能~ 作为一款出色的大语言模型,ChatGPT 实现了人类般的对话交流,最主要是能根据上下文进行互动。 接下来,我将介绍 ChatGPT 在国…...

思通数科开源产品:免费的AI视频监控卫士安装指南

准备运行环境: 确保您的服务器或计算机安装了Ubuntu 18.04 LTS操作系统。 按照产品要求,安装以下软件: - Python 3.9 - Java JDK 1.8 - MySQL 5.5 - Redis 2.7 - Elasticsearch 8.14 - FFmpeg 4.1.1 - RabbitMQ 3.13.2 - Minio (…...

阿里HPN-用于大型语言模型训练的数据中心网络

阿里巴巴HPN:用于大型语言模型训练的数据中心网络 探索大规模语言模型训练新方法:阿里巴巴HPN数据中心网络论文。 摘要 本文介绍了阿里云用于大型语言模型(LLM)训练的数据中心网络HPN。由于LLM和一般云计算之间的差异(例如,在流量模式和容错性方面)&…...

re题(27)BUUFCTF-[MRCTF2020]Transform

BUUCTF在线评测 (buuoj.cn) 先到ida,先看一下字符串 找到主函数 int __cdecl main(int argc, const char **argv, const char **envp) {char Str[104]; // [rsp20h] [rbp-70h] BYREFint j; // [rsp88h] [rbp-8h]int i; // [rsp8Ch] [rbp-4h]sub_402230(argc, argv…...

偶数、奇数、整数与指数

引言 在前面的课程中,我们已经学习了 Python 的基本输入输出、数据类型及其转换、顺序结构、分支结构、循环结构、循环控制语句、字符串类型、列表类型、元组类型、字典类型、集合类型、函数的定义与使用、函数调用与作用域、函数的高级应用、质数、倍数与余数。本课…...

关于c#中异步async和await的理解

之前给大家介绍了所谓异步编程的用法,但是没有细致的理解到,今天想和大家一起探讨一下; 前文: C#笔记14 异步编程Async,await,task类-CSDN博客 异步的起初 应用程序会启动一个进程,一个进程可以有很多…...

mysql等保数据库命令

mysql数据库命令 默认安装位置:C:\Program Files\MySQL\MySQL Server 8.0\bin select version() from dual; desc mysql.user; 查看表中有哪些列 1、SELECT user, host, authentication_string, account_locked ,password_lifetime FROM mysql.user; 查询用户表…...

云平台在大规模设备管理和数据分析中的作用

在当代数字化转型的浪潮中,云平台作为信息技术基础设施的核心组件,扮演着无可替代的角色,尤其在大规模设备管理和数据分析领域,其重要性和影响力日益凸显。本文旨在深入探讨云平台如何通过其独特的优势,促进数据的高效…...

数据结构-树和二叉树

树 和 二叉树 1.树的概念 树 tree 是n(n>0)个节点的有限集 在任意的一个非空树中 (1)有且仅有一个特定的被称为 根(root) 的节点 (2)当n>1时, 其余的节点可分为m(m>0)个互不相交的有限集T1, T2, T3, .... …...

树和二叉树的概念以及结构

一起加油学数据结构 目录 树的概念以及结构 树的概念 树的相关概念 树的表示 二叉树的概念以及结构 二叉树的概念 特殊的二叉树 二叉树的性质 二叉树的存储结构 树的概念以及结构 树的概念 树是一种非线性的数据结构,它是由n(n>0&#xff09…...

c语言习题

第三章 数据类型、运算符与表达式 一 单项选择题 1.下面四个选项中,均不是 c 语言关键字的选项是( )。 A) define IF Type B) getc char printf C) include scanf case D…...

Python 低层多线程接口_thread的用法

_thread是python标准库中的一个低层多线程API,可以在进程中启动线程来处理任务,并且提供了简单的锁机制来控制共享资源的同步访问。本文就_thread模块的用法和特性做个简单的演示。 文章目录 一、进程和线程的区别二、_thread模块的用法2.1 派生线程2.2…...

flutter基础 --dart语法学习

由于想要写一款性能较好,但是又可以一套代码多个平台运行的客户端app,所以选择了flutter 就去看了官方文档,大体发现flutter使用的dart语言和java和js差不多,感觉就是缝合怪。 Dart 是一种面向对象的编程语言,语法上与 Java、JavaScript 等语言有一些相似之处&…...

新手必看:一步步教你绑定常见邮箱到第三方应用(如何绑定QQ、163、Hotmail、Gmail等邮箱)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 邮箱绑定 📒📫 QQ邮箱📫 163邮箱📫 Hotmail邮箱📫 Gmail邮箱📫 Yahoo邮箱📫 iCloud邮箱📫 其他邮箱⚓️ 相关链接 ⚓️📖 介绍 📖 你是否曾经为绑定第三方邮箱而感到困惑?你不是一个人!许多人在尝试将QQ邮…...

mac 怎么查看CPU核数

在 macOS 系统中,可以通过以下几种方法查看 CPU 核心数: 1. 使用“关于本机”查看 点击左上角的苹果图标()。选择“关于本机”。在弹出的窗口中,系统会显示 Mac 的基本信息,包括 CPU 的类型和核心数。比…...

Vue生命周期;Vue路由配置;vue网络请求;vue跨域处理

一&#xff0c;Vue生命周期 <template><div > <h1 click"changeText">{{ info }}</h1></div> </template><script> export default {name: HelloWorld,data(){return{info:"介绍组件生命周期"}},methods:{chang…...

汽车电子电气架构从12V提升至48V,带来那些好处? 包括那些改变?

标签&#xff1a; 汽车电子电气架构&#xff1b; 从12V提升至48V&#xff1b; 汽车电子电气架构从12V提升至48V&#xff0c;带来那些好处&#xff1f; 包括那些改变&#xff1f; 将传统汽车的电子电气架构电压从12V提升至48V&#xff0c;既有显著的优势&#xff0c;也需要对车…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...

NamedParameterJdbcTemplate 使用方法及介绍

NamedParameterJdbcTemplate是 Spring 框架中用于数据库操作的核心类之一&#xff0c;它拓展了JdbcTemplate&#xff0c;通过封装实现命名参数特性&#xff0c;相比传统占位符?&#xff0c;命名参数可读性和维护性更强&#xff0c;能有效避免参数顺序混淆问题。 一、核心支持…...