数据结构--链表和单链表详解及实现
一.前言
数据结构思维导图如下,灰色标记的是之前讲过的,本文将带你走近单链表(红色标记部分),希望大家有所收获🌹🌹

二.链表的定义和概念
在讲单链表之前,我们先学习一下链表
2.1 链表的定义
链表是一种物理存储单元上非连续非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,即
- 逻辑结构:线性
- 物理结构:非线性
2.2 节点的构成要素
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。即数据+指向下一个结点的指针,节点常用结构体实现。
struct ListNode
{
LTDataType data;
struct ListNode* next;
};
2.3 与数组结构的对比差异
| 数组 | 链表 | |
|---|---|---|
| 存储方式 | 连续存储 需要预先分配固定大小的内存空间 | 非连续存储,通过指针连接 动态分配内存,不需要预先确定大小 |
| 内存使用 | 空间利用率高 (因为所有元素都紧密排列) 可能存在未使用的空间(e.g.数组大小固定但实际使用元素少) | 空间利用率相对较低 每个节点需要额外的内存来存储指针 |
| 插入和删除操作 | 可能需要移动大量元素以保持连续性 时间复杂度为O(n),因为可能需要移动插入点之后的所有元素 | 通常只需要改变指针,不需要移动元素 时间复杂度为O(1) (已知插入或删除位置的节点) |
| 随机访问 | 支持高效的随机访问,可通过索引快速访问任意元素 访问时间复杂度为O(1) | 不支持高效的随机访问,必须从头节点开始遍历链表 访问时间复杂度为O(n)。 |
| 空间局部性 | 有很好的空间局部性,因为元素连续存储,适合缓存优化 | 空间局部性差,因为元素分散存储,可能导致缓存未命中 |
| 实现复杂度 | 实现简单,大多数编程语言内置支持 | 实现相对复杂,需要手动管理节点和指针 |
| 适用场景 | 适合需要频繁随机访问的场景 适合元素数量已知且变化不大的场景 | 适合插入和删除操作频繁的场景 适合元素数量频繁变化的场景 |
三.链表的分类
链表的结构非常多样,以下情况组合起来就有8种(2*2*2)链表结构

链表说明:


虽然有这么多的链表结构,但是我们实际中最常用的还是两种结构:
- 单链表:不带头单向不循环链表
- 双向链表:带头双向循环链表
四.单链表
前期准备
创建三个文件:
- SList.h: 存放各种头文件和函数声明
- SLIst.c : 各种函数的实现
- test.c: 测试和执行代码 最好写完一部分测试一部分 防止后期调试一堆bug
实现
首先在头文件中写上
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
接下来我们一步步实现单链表各种操作
1.定义链表结构
typedef int SLTDataType;//方便之后一键替换类型typedef struct SListNode
{SLTDataType data; //结点数据struct SListNode* next; //指针保存下⼀个结点的地址
}SLTNode;
2.申请新节点和打印函数
因为后面会多次用到申请新节点和打印函数,所以我们把它们都各自封装成函数方便调用
//申请新节点
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("malloc fail!");exit(1);}node->data = x;node->next = NULL;return node;
}
//打印函数
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
3.查找数据
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{assert(phead);SLTNode* pcur = phead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}//没有找到return NULL;
}
4.插入操作
包括尾插、头插、在指定位置之前插入数据、在指定位置之后插入数据
(1)尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);//pphead --> &plist// *pphead --> plist//申请新节点SLTNode* newnode = SLTBuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{//找尾结点SLTNode* pcur = *pphead;while (pcur->next){pcur = pcur->next;}//pcur newnodepcur->next = newnode;}
}
(2)头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//newnode *ppheadnewnode->next = *pphead;*pphead = newnode;
}
(3)在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);if (pos == *pphead){SLTPushFront(pphead, x);}else{SLTNode* newnode = SLTBuyNode(x);//找prev :pos的前一个结点SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//prev newnode --> posnewnode->next = pos;prev->next = newnode;}
}
(4)在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);//pos newnode --> pos->nextnewnode->next = pos->next;pos->next = newnode;
}
测试如下

5.删除操作
包括尾删、头删、删除指定节点、删除指定位置之后的结点、删除指定位置之前的结点(该操作是给你们留的作业😜 学完这篇自己独立实现一下 答案可以让我发给你或者其实调试通过了应该没什么问题跟前面的实现逻辑一样)
(1)尾删
void SLTPopBack(SLTNode** pphead)
{//链表为空:不可以删除assert(pphead && *pphead);//处理只有一个结点的情况:要删除的就是头结点 if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{//找 prev ptailSLTNode* ptail = *pphead;SLTNode* prev = NULL;while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);ptail = NULL;}
}
测试如下

(2)头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;//*pphead --> nextfree(*pphead);*pphead = next;
}
(3)删除指定节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);//头删if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//prev pos pos->nextprev->next = pos->next;free(pos);pos = NULL;}
}
(4)删除指定位置之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);//pos pos->next pos->next->nextSLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}
6.销毁链表
void SListDestroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

五.总结
单链表的详细实现代码已经上传到我的资源了,大家点进主页或者在本文最上方可以下载查看,自己去写一下,边写边调试会更容易理解和掌握。
接下来会逐步介绍上述思维导图数据结构剩下的部分,创作不易,希望大家多多支持,有什么想法欢迎讨论🌹🌹
相关文章:
数据结构--链表和单链表详解及实现
一.前言 数据结构思维导图如下,灰色标记的是之前讲过的,本文将带你走近单链表(红色标记部分),希望大家有所收获🌹🌹 二.链表的定义和概念 在讲单链表之前,我们先学习一下链表 2.1 链表的定义 链表是一种…...
vue3基础知识
书接上文,这篇继续来学习vue3的核心语法,可以先看上一篇再来看这篇效果更好。 1. computed computed 用于创建 计算属性,即基于其他响应式数据的值动态计算并缓存的属性。它的主要作用是优化性能和提高代码的可维护性,避免不必要…...
【Linux系统】Ubuntu 缓冲区机制
在Ubuntu中,和其他操作系统有个不一样的机制:缓冲区。这篇文章是对与缓冲区的详细介绍。 在 Ubuntu 中(以及其他基于 Linux 的操作系统),缓冲区(Buffer)是内核用于优化 I/O 操作的重要机制。它…...
ChatGPT 最新推出的 Pro 订阅计划,具备哪些能力 ?
OpenAI 最近推出了 ChatGPT Pro,这是一个每月收费 200 美元的高级订阅计划,旨在为用户提供对 OpenAI 最先进模型和功能的高级访问。 以下是 ChatGPT Pro 的主要功能和能力: 高级模型访问: o1 模型:包括 o1 和 o1 Pro…...
数据结构理论
内容来源青岛大学数据结构与算法课程,链接:数据结构与算法基础(青岛大学-王卓)_哔哩哔哩_bilibili 绪论 数据结构概述 数据结构和算法的定义:我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存…...
es 3期 第14节-全文文本分词查询
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
六安市第二届网络安全大赛复现
misc 听说你也喜欢俄罗斯方块? ppt拼接之后 缺三个角补上 flag{qfnh_wergh_wqef} 流量分析 流量包分离出来一个压缩包 出来一张图片 黑色代表0白色代表1 101010 1000 rab 反的压缩包 转一下 密码:拾叁拾陆叁拾贰陆拾肆 密文:4p4n5758…...
Sarcomere仿人灵巧手ARTUS,20个自由度拓宽机器人作业边界
Sarcomere Dynamics 是一家深度技术先驱,通过开发和商业化仿人机械来改变机器人行业。专注于为科研人员,系统集成商和制造商提供更实惠、更轻便且更灵活的末端执行器替代品。凭借创新的致动器技术,创造了一款紧凑、轻便且非常坚固的机械手Art…...
Django drf 基于serializers 快速使用
1. 安装: pip install djangorestframework 2. 添加rest_framework到您的INSTALLED_APPS设置。 settings.pyINSTALLED_APPS [...rest_framework, ] 3. 定义模型 models.pyfrom django.db import modelsclass BookModel(models.Model):name models.CharField(max_length64)…...
pycharm集成环境中关于安装sklearn库报错问题分析及解决
在输入pip install sklearn后,出现如下提示: pip install sklearn Collecting sklearn Using cached sklearn-0.0.post12.tar.gz (2.6 kB) Installing build dependencies ... done Getting requirements to build wheel ... error error: subprocess-…...
AI - 浅聊一下基于LangChain的AI Agent
AI - 浅聊一下基于LangChain的AI Agent 大家好,今天我们来聊聊一个很有意思的主题: AI Agent ,就是目前非常流行的所谓的AI智能体。AI的发展日新月异,都2024年末了,如果此时小伙伴们对这个非常火的概念还不清楚的话&a…...
《【Linux】深入理解进程管理与 fork 系统调用的实现原理》
一、引言 在 Linux 操作系统中,进程管理是核心功能之一。进程是操作系统进行资源分配和调度的基本单位。理解进程管理的原理以及 fork 系统调用的实现对于深入掌握 Linux 系统的运行机制至关重要。本文将深入探讨 Linux 中的进程管理以及 fork 系统调用的实现原理&a…...
docker-compose部署skywalking 8.1.0
一、下载镜像 #注意 skywalking-oap-server和skywalking java agent版本强关联,版本需要保持一致性 docker pull elasticsearch:7.9.0 docker pull apache/skywalking-oap-server:8.1.0-es7 docker pull apache/skywalking-ui:8.1.0二、部署文件docker-compose.yam…...
AI 总结的的 AI 学习路线
一、入门阶段:数学基础与编程语言 数学基础 线性代数 当年白纸黑字推演, 都是泪啊,草稿本都用了一卷。 学习向量、矩阵的基本概念,包括向量的加法、减法、点积和叉积,矩阵的乘法、转置等运算。例如,在计算…...
离散傅里叶级数(DFS)详解
1. 引言 离散傅里叶级数(Discrete Fourier Series, DFS)是信号处理领域中一项基础且重要的数学工具,用于分析和处理周期性的离散信号。它通过将离散时间信号表示为一组正弦和余弦的和,从而使得信号在频域上得到更清晰的描述。与连…...
Java 类加载机制详解
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
1.1 Beginner Level学习之“编写简单的发布服务器和订阅服务器”(第十一节)
学习大纲: 1. 编写发布服务器节点 在 ROS 中,节点是连接到 ROS 网络的可执行文件。我创建了一个名为 talker 的发布者节点,它会向一个主题 chatter 不断发送消息。 首先,进入你的工作包 beginner_tutorials(假设你已…...
AIQuora:开启论文写作新篇章
在这个信息爆炸的时代,学术写作已成为研究者不可或缺的技能。然而,面对繁重的写作任务,许多学者和学生常常感到力不从心。AIQuora,一个专业的文理工科论文智能写作助手,以其免费开题报告生成功能,为学术写作…...
【C语言】库函数常见的陷阱与缺陷(1):字符串处理函数
目录 一、 strcpy 函数 1.1. 功能与常见用法 1.2. 陷阱与缺陷 1.3. 安全替代 1.4. 代码示例 二、strcat 函数 2.1. 功能与常见用法 2.2. 陷阱与缺陷 2.3. 安全替代 2.4. 代码示例 三、strcmp 函数 3.1. 功能与常见用法 3.2. 陷阱与缺陷 3.3. 安全替代 3.4. 代…...
Mysql索引原理及优化——岁月云实战笔记
根据Mysql索引原理及优化这个博主的视频学习,对现在的岁月云项目中mysql进行优化,我要向这个博主致敬,之前应用居多,理论所知甚少,于是将学习到东西,应用下来,看看是否有好的改观。 1 索引原理…...
PromptCraft-Robotics:基于LLM的机器人任务规划与安全控制实践
1. 项目概述与核心价值最近在机器人编程和AI应用领域,一个名为“PromptCraft-Robotics”的项目在开发者社区里引起了不小的讨论。这个项目由微软开源,其核心目标直指一个困扰许多开发者和研究者的痛点:如何让大型语言模型(LLM&…...
体育科学论文降AI工具免费推荐:2026年体育科学研究毕业论文知网AIGC超标4.8元亲测达标完整指南
体育科学论文降AI工具免费推荐:2026年体育科学研究毕业论文知网AIGC超标4.8元亲测达标完整指南 帮同学选过降AI工具,综合价格、效果、保障来看,推荐嘎嘎降AI(www.aigcleaner.com)。 4.8元,达标率99.26%&a…...
3步玩转APK下载:开源APKMirror客户端的终极实战指南
3步玩转APK下载:开源APKMirror客户端的终极实战指南 【免费下载链接】APKMirror 项目地址: https://gitcode.com/gh_mirrors/ap/APKMirror 你是否曾因官方应用商店找不到某个历史版本而苦恼?是否担心第三方下载站点的安全性?今天&…...
腾讯云秒杀活动是什么?2026年最新参与指南(附抢购技巧)
腾讯云秒杀活动是什么?怎么参与?本文将详细解析腾讯云秒杀活动规则、参与入口、抢购技巧及备选方案,助力大家低成本开启云端之旅! 一、活动介绍 腾讯云秒杀活动是腾讯云官方推出的限量限时抢购活动,主打高性价比的轻量…...
STM32嵌入式开发入门:从硬件配置到项目实战的完整学习路径
1. 项目概述:从零到一,如何构建你的STM32知识体系很多刚接触嵌入式开发的朋友,拿到一块STM32开发板,看着满屏的英文手册和复杂的库函数,第一反应往往是“从哪开始?”。这感觉就像面对一座零件齐全但没图纸的…...
如何用开源C模拟器在PC上运行Nintendo Switch游戏:Ryujinx技术深度解析
如何用开源C#模拟器在PC上运行Nintendo Switch游戏:Ryujinx技术深度解析 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx是一款用C#编写的开源Nintendo Switch模拟器…...
AI教材生成新趋势!低查重AI工具,让教材编写不再困难!
教材创作与AI工具助力 教材初稿终于写好了,然而修改和优化的过程却像是一场“折磨”!逐字逐句地检查逻辑错误和知识点不准确的地方,真的是耗费了不少时间;调整一个章节的结构,就会影响到后面好多部分,修改…...
别再让电机乱转了!手把手教你用STM32的TIM3和L298N实现精准PWM调速(附完整工程源码)
STM32与L298N电机控制实战:从原理到精准调速的完整指南 在智能小车、机械臂或自动化设备开发中,直流电机控制是最基础却最容易出问题的环节。很多初学者在第一次连接STM32和L298N驱动模块时,都会遇到电机不转、乱转或速度不稳的情况。本文将彻…...
别再死记硬背了!用这个‘水管阀门’比喻,5分钟搞懂N沟道和P沟道MOS管工作原理
水管阀门模型:5分钟掌握MOS管的核心逻辑 第一次接触MOS管时,那些载流子、耗尽层、反型层的专业术语就像一堵高墙,把我们对电子世界的好奇心挡在外面。但当我发现可以用厨房水龙头的原理来理解这些抽象概念时,一切都变得清晰起来。…...
别再手动拼接URL了!若依集成JimuReport报表,一个优雅的Token传递方案
若依系统与JimuReport深度集成:Token安全传递的架构实践 在当今企业级应用开发中,报表功能是不可或缺的核心模块,而如何将第三方报表系统无缝集成到现有框架中,同时确保认证体系的安全性与一致性,一直是开发者面临的挑…...
