链表详解:定义、作用、应用场景及与数组的区别(C/C++ 实战)

发布时间:2026/8/29 12:40:14

链表详解:定义、作用、应用场景及与数组的区别(C/C++ 实战)
1. 什么是链表链表是一种物理存储单元上非连续、非顺序的线性数据结构它由一系列节点Node组成。每个节点包含两部分一部分是存储数据元素的数据域data另一部分是存储下一个节点地址的指针域next。与数组不同链表中的各个节点在内存中并不需要连续存放节点之间通过指针相互连接形成一个链式结构。链表的第一个节点称为头节点head最后一个节点的指针域指向空NULL表示链表的结束。链表的核心思想是用指针把分散在内存各处的节点串联起来从而在逻辑上保持线性顺序。这种设计使得链表在插入和删除操作上具有天然的优势因为只需要修改指针的指向而不需要移动大量数据。2. 链表的作用链表在程序设计中主要解决以下几类问题动态内存管理链表可以在运行时按需分配和释放节点内存不需要预先知道数据总量适合数据规模不确定的场景。高效的插入与删除在已知位置插入或删除节点时链表只需要修改指针时间复杂度为 O(1)而数组需要移动大量元素时间复杂度为 O(n)。内存碎片利用链表不要求连续内存空间可以充分利用内存中的零散空闲区域。实现复杂数据结构的基础链表是栈、队列、哈希表链地址法、图的邻接表等许多高级数据结构的基础构件。3. 链表与数组的区别数组和链表是两种最基础的线性数据结构它们在内存布局、操作效率和适用场景上有显著差异。下面通过一个表格进行对比对比维度数组链表内存布局连续内存空间非连续节点分散存储内存分配静态分配或动态一次性分配动态按需分配逐个创建节点访问方式支持随机访问通过下标 O(1) 定位只能顺序访问需从头遍历 O(n)插入/删除需要移动大量元素O(n)只需修改指针O(1)已知位置时空间开销无额外指针开销但可能浪费预分配空间每个节点额外存储指针空间开销较大缓存友好性连续存储CPU 缓存命中率高节点分散缓存命中率低扩容需要重新分配更大的内存并复制数据直接新增节点即可无需整体搬迁简单来说数组擅长随机访问和缓存友好但插入删除代价高链表擅长频繁插入删除但随机访问能力弱。选择哪种结构取决于具体业务场景对操作类型的侧重。4. 链表的常见应用场景链表在真实项目和系统中有广泛的应用主要包括操作系统内存管理空闲内存块通常用链表组织便于分配和回收。文件系统文件分配表FAT和部分日志结构文件系统使用链表思想管理存储块。哈希表冲突解决链地址法用链表存储哈希冲突的元素。图的邻接表每个顶点的邻接边用链表存储节省空间。LRU 缓存淘汰哈希表 双向链表实现 O(1) 的访问和淘汰。多项式运算稀疏多项式用链表存储非零项节省存储空间。大数运算超出基本类型范围的大整数用链表按位存储。栈和队列的实现链表可实现动态扩容的栈和队列。5. C 语言实现单链表下面用 C 语言实现一个完整的单链表包含创建、插入、删除、遍历和销毁等基本操作。#include stdio.h #include stdlib.h // 定义链表节点结构体 typedef struct Node { int data; // 数据域 struct Node *next; // 指针域指向下一个节点 } Node; // 创建新节点 Node* createNode(int value) { Node *newNode (Node*)malloc(sizeof(Node)); if (newNode NULL) { printf(内存分配失败\n); return NULL; } newNode-data value; newNode-next NULL; return newNode; } // 头插法在链表头部插入节点 Node* insertAtHead(Node *head, int value) { Node *newNode createNode(value); newNode-next head; // 新节点指向原头节点 return newNode; // 新节点成为新的头节点 } // 尾插法在链表尾部插入节点 Node* insertAtTail(Node *head, int value) { Node *newNode createNode(value); if (head NULL) { return newNode; // 空链表新节点即头节点 } Node *current head; while (current-next ! NULL) { current current-next; // 遍历到最后一个节点 } current-next newNode; // 尾节点指向新节点 return head; } // 删除指定值的第一个节点 Node* deleteNode(Node *head, int value) { if (head NULL) return NULL; // 如果要删除的是头节点 if (head-data value) { Node *temp head; head head-next; free(temp); return head; } // 遍历查找目标节点的前一个节点 Node *current head; while (current-next ! NULL current-next-data ! value) { current current-next; } if (current-next ! NULL) { Node *temp current-next; current-next temp-next; // 跳过目标节点 free(temp); // 释放内存 } return head; } // 遍历打印链表 void printList(Node *head) { Node *current head; while (current ! NULL) { printf(%d - , current-data); current current-next; } printf(NULL\n); } // 释放整个链表 void freeList(Node *head) { Node *current head; while (current ! NULL) { Node *temp current; current current-next; free(temp); } } int main() { Node *head NULL; // 头插法构建链表3 - 2 - 1 - NULL head insertAtHead(head, 1); head insertAtHead(head, 2); head insertAtHead(head, 3); printf(头插法结果: ); printList(head); // 尾插法追加节点3 - 2 - 1 - 4 - 5 - NULL head insertAtTail(head, 4); head insertAtTail(head, 5); printf(尾插法结果: ); printList(head); // 删除值为 2 的节点 head deleteNode(head, 2); printf(删除节点 2 后: ); printList(head); // 释放链表内存 freeList(head); return 0; }运行结果如下头插法结果: 3 - 2 - 1 - NULL 尾插法结果: 3 - 2 - 1 - 4 - 5 - NULL 删除节点 2 后: 3 - 1 - 4 - 5 - NULL这段代码演示了链表最核心的操作头插法利用新节点指向原头节点实现 O(1) 插入尾插法需要遍历到末尾再连接删除节点时先找到目标节点的前驱再修改指针并释放内存。注意每次 malloc 分配节点后使用完毕必须 free 释放否则会造成内存泄漏。6. C 实现双向链表C 中除了可以用 struct 手动实现链表标准库还提供了std::list双向链表和std::forward_list单向链表。下面先手动实现一个双向链表再展示标准库的用法。#include iostream using namespace std; // 双向链表节点 struct DNode { int data; DNode *prev; // 指向前驱 DNode *next; // 指向后继 DNode(int val) : data(val), prev(nullptr), next(nullptr) {} }; // 双向链表类 class DoublyLinkedList { private: DNode *head; DNode *tail; public: DoublyLinkedList() : head(nullptr), tail(nullptr) {} // 在尾部插入 void pushBack(int value) { DNode *newNode new DNode(value); if (tail nullptr) { head tail newNode; // 空链表 } else { tail-next newNode; newNode-prev tail; tail newNode; } } // 在头部插入 void pushFront(int value) { DNode *newNode new DNode(value); if (head nullptr) { head tail newNode; } else { newNode-next head; head-prev newNode; head newNode; } } // 删除指定值的第一个节点 void remove(int value) { DNode *current head; while (current ! nullptr) { if (current-data value) { if (current-prev ! nullptr) { current-prev-next current-next; } else { head current-next; // 删除的是头节点 } if (current-next ! nullptr) { current-next-prev current-prev; } else { tail current-prev; // 删除的是尾节点 } delete current; return; } current current-next; } } // 正向遍历 void printForward() { DNode *current head; while (current ! nullptr) { cout current-data - ; current current-next; } cout NULL endl; } // 反向遍历 void printBackward() { DNode *current tail; while (current ! nullptr) { cout current-data - ; current current-prev; } cout NULL endl; } // 析构函数释放所有节点 ~DoublyLinkedList() { DNode *current head; while (current ! nullptr) { DNode *temp current; current current-next; delete temp; } } }; int main() { DoublyLinkedList list; list.pushBack(10); list.pushBack(20); list.pushBack(30); list.pushFront(5); cout 正向遍历: ; list.printForward(); cout 反向遍历: ; list.printBackward(); list.remove(20); cout 删除 20 后正向遍历: ; list.printForward(); return 0; }双向链表每个节点多了一个指向前驱的指针因此可以双向遍历删除节点时不需要像单链表那样寻找前驱节点代码更简洁。代价是每个节点多占用一个指针的内存空间。7. C 标准库链表用法在实际开发中除非有特殊需求通常直接使用 C 标准库提供的链表容器避免重复造轮子。下面演示std::list的常用操作。#include iostream #include list using namespace std; int main() { // 创建双向链表 listint myList; // 尾部插入 myList.push_back(10); myList.push_back(20); myList.push_back(30); // 头部插入 myList.push_front(5); // 遍历输出 cout 链表元素: ; for (int val : myList) { cout val ; } cout endl; // 在指定位置插入在第二个位置插入 15 auto it myList.begin(); advance(it, 2); // 迭代器前进 2 步 myList.insert(it, 15); cout 插入 15 后: ; for (int val : myList) { cout val ; } cout endl; // 删除指定值 myList.remove(20); cout 删除 20 后: ; for (int val : myList) { cout val ; } cout endl; // 获取链表大小 cout 链表大小: myList.size() endl; // 判断是否为空 cout 是否为空: (myList.empty() ? 是 : 否) endl; return 0; }运行结果如下链表元素: 5 10 20 30 插入 15 后: 5 10 15 20 30 删除 20 后: 5 10 15 30 链表大小: 4 是否为空: 否std::list是双向链表支持 O(1) 的头部和尾部插入删除也支持在任意已知迭代器位置插入删除。需要注意的是std::list不支持随机访问不能直接用下标取值必须通过迭代器遍历。8. 链表常见变体除了最基本的单链表和双向链表还有几种常见的链表变体在不同场景下各有优势循环链表尾节点的 next 指向头节点形成环形结构。适合需要循环遍历的场景如操作系统的进程调度轮转、约瑟夫环问题。双向循环链表头节点的 prev 指向尾节点尾节点的 next 指向头节点。STL 的std::list内部就是这种结构便于从任意一端快速遍历。带头节点的链表在真正的头节点之前增加一个不存储数据的哨兵节点统一了空表和非空表的操作逻辑避免大量判空分支。跳表Skip List在有序链表上增加多层索引实现 O(log n) 的查找效率是 Redis 有序集合的底层实现之一。9. 总结链表是一种通过指针串联节点的线性数据结构它的核心价值在于动态内存管理和高效的插入删除操作。与数组相比链表牺牲了随机访问能力换来了更灵活的内存使用和更低的插入删除成本。在实际开发中选择数组还是链表需要根据业务场景判断如果以随机访问为主、数据规模相对固定优先选择数组如果数据规模动态变化大、插入删除频繁链表是更合适的选择。C 语言中需要手动管理节点内存C 则可以直接使用std::list或std::forward_list标准库容器兼顾效率和安全性。

相关新闻

4个月1亿美元,生物世界模型为何需要“数据发电厂”?

4个月1亿美元,生物世界模型为何需要“数据发电厂”?

2026/8/29 12:40:14

最近关注的不是“又一个百亿参数大模型”,而是 TechBio 赛道里出现的一个新组合:一家公司在 4 个月里融进 1 亿美元,同时建齐 3 座“数据发电厂”,目标是训练一个“生物世界模型”。这个标题信息量很密,但它不是一个普…

大模型+形式化验证:从GPT-5.6与Fable协作看AI数学证明闭环

大模型+形式化验证:从GPT-5.6与Fable协作看AI数学证明闭环

2026/8/29 12:40:14

近几天,技术社区里讨论最多的话题之一,是“GPT-5.6 和 Fable 联手解决了一道悬了 25 年的数学难题”这则消息。由于公开细节还不完整,这里不猜测难题本身,也不对两个产品下结论,而是把它当成一个更好的技术问题的起点&…

Design Compiler:边界优化(Boundary Optimization)

Design Compiler:边界优化(Boundary Optimization)

2026/8/29 12:30:14

相关阅读 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 前言 默认情况下,Design Compiler在综合时不会跨越层次结构进行优化,这会导致一些关键路径的逻辑无法得到简化。边界优化(Boundary O…

Vue3进度条(Progress)

Vue3进度条(Progress)

2026/8/29 13:50:22

Vue2进度条(Progress) 可自定义设置以下属性: 进度条宽度(width),单位 px,类型:string | number,默认 undefined;type: line 时,为进度条宽度&am…

Vue3分割线(Divider)

Vue3分割线(Divider)

2026/8/29 13:50:22

可自定义设置以下属性: 分割线标题的位置(orientation),类型:left | center | right,默认 center 标题和最近 left/right 边框之间的距离,去除了分割线,同时 orientation 必须为 le…

2026年ai建站哪家技术强,多平台对比来啦!

2026年ai建站哪家技术强,多平台对比来啦!

2026/8/29 13:50:22

2026年ai建站哪家技术强,多平台对比来啦!艾瑞咨询《2026年中国企业数字化建站行业白皮书》给出一组对照:国内AI建站渗透率已破68%,但抽样超1200家中小企业中仅31%在AI生成站点半年后仍持续续费且搜索流量正向增长。 深圳某3C配件品…

千问赢在生态:本地部署、开发者集成与办公场景全解析

千问赢在生态:本地部署、开发者集成与办公场景全解析

2026/8/29 13:50:22

看到“苹果删了千问,但阿里赢了”这个说法时,我第一反应不是去考证事件细节,而是想另一个问题:一个 AI 产品如果只是失去某个渠道入口,为什么还能被这么多人继续讨论?千问给出的答案,不是把流量…

MySQL存储过程实战:从设计到性能优化的完整指南

MySQL存储过程实战:从设计到性能优化的完整指南

2026/8/29 13:50:22

1. 项目概述:从“一次性脚本”到“可复用引擎” 如果你写过一段时间数据库应用,尤其是处理过复杂的报表生成、数据清洗或者需要高频执行相同逻辑的业务,你大概率会对满屏重复或相似的SQL语句感到头疼。今天要聊的“存储过程”,就是…

芯片厂落地背后:嵌入式开发必懂的SoC启动与固件烧录全解析

芯片厂落地背后:嵌入式开发必懂的SoC启动与固件烧录全解析

2026/8/29 13:40:22

半导体制造业的每一次选址落地,都会牵动芯片设计、设备、材料、封测等一系列产业链条。最近“马斯克 TeraFab 芯片厂在得州进入协议阶段”的消息在科技圈传播得很广,很多做嵌入式和芯片相关开发的同学也来问我:这个“协议阶段”到底是什么意思…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/29 10:22:10

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/28 7:34:42

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

四款热门降AI工具测评:研究生和本科生怎么选?

四款热门降AI工具测评:研究生和本科生怎么选?

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

论文降AI率免费攻略:自查、提示词与工具推荐

论文降AI率免费攻略:自查、提示词与工具推荐

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

2026/8/29 0:09:39

前言:预算有限的企业更关心投入能否形成可持续的品牌资产。评估北京GEO优化服务商时,不能只比较单篇内容或单月报价,还要看是否能够把问题词、官网、信源和监测串成完整链路。本期重点放在预算配置、试点范围和交付边界,帮助企业先…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/28 7:35:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/28 7:34:51

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/28 7:34:35

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…