“链表” 咋理解?用 “糖葫芦串” 讲透单链表 / 双向链表
很多零基础小伙伴看到 “链表” 就联想到 “复杂的指针、节点”,其实它就是 “数据像糖葫芦一样串起来的存储结构”—— 每颗糖葫芦是 “数据节点”,串糖葫芦的签子是 “指针”,通过签子就能找到下一颗(或上一颗)糖葫芦。今天用 “糖葫芦串” 类比,讲透单链表、双向链表的结构特点,以及遍历、插入、删除这 3 个考试高频操作,看完你会发现,链表考点其实就是 “串糖葫芦的逻辑”。
先明确:为啥要学链表?考试高频且易拿分!
链表是数据结构模块的 “核心考点”,上午选择题每年 1 道(比如 “单链表和双向链表的区别”“链表插入操作的步骤”),下午算法题偶尔考 “链表代码补全”,占数据结构模块 20% 的分值。而且链表的操作逻辑固定,记清 “糖葫芦串” 的类比,就能轻松应对所有考题。
用 “糖葫芦串” 类比:单链表 vs 双向链表的结构
不管是单链表还是双向链表,核心都是 “节点 + 指针”,就像糖葫芦是 “山楂 + 签子”,区别只在 “签子的方向”—— 单链表是 “单向签子”(只能从左往右找),双向链表是 “双向签子”(能左能右找):
1. 单链表:“单向签子的糖葫芦串”,只能从左往右找
单链表的每个节点包含 “数据” 和 “一个指针(指向 next 节点)”,就像每颗山楂只串了一根 “向右的签子”,只能从第一颗找到第二颗,再从第二颗找到第三颗,没法回头找前一颗。
类比对象 | 单链表中的概念 | 核心作用 | 图示(文字简化版) |
山楂 | 节点(Node) | 存储具体数据(如数字 5、字符 “A”) | [数据:5] |
向右的签子 | 指针(next 指针) | 指向 “下一个节点”,建立节点间的联系 | → |
整串糖葫芦 | 单链表(Singly Linked List) | 存储一组有序数据 | [5]→[8]→[3]→[null](null 表示末尾) |
关键特点:
- 只能 “从表头往表尾” 遍历(像从左往右啃糖葫芦),没法从表尾往表头走;
- 最后一个节点的 next 指针指向 “null”(像最后一颗山楂没有后续的签子)。
2. 双向链表:“双向签子的糖葫芦串”,能左能右找
双向链表的每个节点除了 “数据”,还包含 “两个指针”—— 一个 next 指针(指向后一个节点)、一个 prev 指针(指向前一个节点),就像每颗山楂串了 “左右两根签子”,既能从左往右找,也能从右往左找。
类比对象 | 双向链表中的概念 | 核心作用 | 图示(文字简化版) |
山楂 | 节点(Node) | 存储具体数据 | [数据:5] |
向右的签子 | next 指针 | 指向 “下一个节点” | → |
向左的签子 | prev 指针 | 指向 “前一个节点” | ← |
整串糖葫芦 | 双向链表(Doubly Linked List) | 存储一组有序数据,支持双向遍历 | null←[5]↔[8]↔[3]→null |
关键特点:
- 支持 “双向遍历”(既可以从左往右啃,也能从右往左啃),比单链表灵活;
- 第一个节点的 prev 指针指向 “null”,最后一个节点的 next 指针指向 “null”(首尾都没有多余的签子)。
链表的 3 个高频操作:遍历、插入、删除(考试必记!)
考试最常考链表的 “遍历”“插入”“删除” 操作,用 “糖葫芦串” 的操作类比,步骤一看就懂,以单链表为例(双向链表操作类似,多一步 prev 指针调整):
1. 遍历:“从左往右啃糖葫芦”,逐个访问节点
核心逻辑:从 “表头节点” 开始,通过 next 指针依次访问下一个节点,直到遇到 “null”(末尾)。
操作步骤 | 糖葫芦串类比 | 代码逻辑(简化版,考试看懂即可) |
1. 准备工作 | 拿起糖葫芦的第一颗山楂 | 定义指针 current = 表头节点 |
2. 访问当前节点 | 啃当前手里的山楂 | 读取 current 节点的数据 |
3. 找下一个节点 | 用签子找到下一颗山楂 | current = current.next |
4. 停止条件 | 啃到最后一颗,没有后续山楂 | 当 current == null 时停止 |
考试考点: 单链表遍历只能 “从表头到表尾”,双向链表可以 “双向遍历”,选择题常考 “下列哪种链表支持从表尾往表头遍历?”(答案:双向链表)。
2. 插入:“在糖葫芦中间加一颗山楂”,调整指针即可
以 “在节点 [5] 和 [8] 之间插入节点 [6]” 为例,核心是 “先连新节点,再断原指针”,避免节点丢失(像加山楂时先串新的,再调整签子)。
操作步骤 | 糖葫芦串类比 | 代码逻辑(简化版) |
1. 找到插入位置 | 找到要插入的两颗山楂([5] 和 [8]) | 找到前驱节点 prev = [5],后继节点 next = [8] |
2. 连新节点的 next 指针 | 用新山楂的签子连向后继山楂 [8] | 新节点.next = next([6].next = [8]) |
3. 改前驱节点的 next 指针 | 把前驱山楂 [5] 的签子改连新山楂 [6] | prev.next = 新节点([5].next = [6]) |
关键提醒: 步骤不能反!如果先改前驱节点的指针,会找不到后继节点 [8](像先拆了 [5] 的签子,就找不到 [8] 在哪了)。
3. 删除:“从糖葫芦中间去掉一颗山楂”,重新串签子
以 “删除节点 [8](位于 [5] 和 [3] 之间)” 为例,核心是 “让前驱节点直接连后继节点,跳过要删除的节点”(像去掉 [8] 后,把 [5] 的签子直接连 [3])。
操作步骤 | 糖葫芦串类比 | 代码逻辑(简化版) |
1. 找到删除位置 | 找到要删的山楂 [8],以及前后的 [5] 和 [3] | 找到前驱节点 prev = [5],待删节点 del = [8] |
2. 改前驱节点的 next 指针 | 把 [5] 的签子跳过 [8],直接连 [3] | prev.next = del.next([5].next = [3]) |
3. (可选)释放节点 | 把去掉的山楂 [8] 扔掉 | (编程语言相关,考试不考具体释放细节) |
考试考点: 单链表删除必须 “找到前驱节点”,如果只知道待删节点,没法直接删除(像只拿到 [8],不知道 [5] 在哪,就没法串签子);双向链表因为有 prev 指针,能直接找到前驱节点,删除更方便。
单链表 vs 双向链表:核心区别对比(考试必背!)
为了避免记混,整理成对比表,重点记 “遍历方向”“操作效率”“空间开销” 这 3 个考试高频维度:
对比维度 | 单链表 | 双向链表 | 记忆技巧(糖葫芦类比) |
遍历方向 | 只能从表头→表尾(单向啃) | 表头→表尾、表尾→表头(双向啃) | 单签子只能往右,双签子能左能右 |
插入 / 删除效率 | 找前驱节点需要遍历,效率低 | 通过 prev 指针直接找前驱,效率高 | 双签子能直接找到前后山楂,不用从头找 |
空间开销 | 每个节点只存 1 个指针,开销小 | 每个节点存 2 个指针,开销大 | 双签子比单签子费材料(指针占内存) |
适用场景 | 数据只需单向访问、内存紧张的场景 | 数据需要双向访问的场景(如浏览器前进 / 后退、链表排序) | 看视频只快进用单链,又快进又后退用双链 |
真题练手:2 道题带你秒会(都是送分题!)
1.(2023 上午第 40 题)下列关于单链表和双向链表的说法,正确的是?
A. 单链表支持从表尾往表头遍历
B. 双向链表每个节点只包含 1 个指针
C. 单链表删除节点时必须找到前驱节点
D. 双向链表的空间开销比单链表小
解析: 逐一排除错误选项:A(单链表只能单向遍历)、B(双向链表有 2 个指针)、D(双向链表空间开销更大);C(单链表没有 prev 指针,必须找前驱才能删除)正确。
答案:C
2.(2022 上午第 41 题)某场景需要频繁从链表的两端添加和删除节点,且需要双向遍历数据,适合采用哪种链表?
A. 单链表 B. 双向链表 C. 循环链表 D. 静态链表
解析: 题干关键词 “双向遍历”“两端操作”,双向链表支持双向遍历,且通过 prev/next 指针能快速操作两端节点;单链表不支持双向遍历,循环链表和静态链表不符合场景。
答案:B
零基础总结:1 句口诀 + 1 张表(直接背!)
- 口诀:“单链单向走,双链双向游;插入删前驱,双链不用愁”(概括单 / 双链的遍历和操作特点);
- 必背对比表:记清 “遍历方向、操作效率、空间开销” 的区别,考试看到选项就能对应,不用纠结复杂定义。
通过 “糖葫芦串” 的类比,链表的结构和操作逻辑基本能轻松掌握,后续复习时只需偶尔回顾对比表和操作步骤,就能应对所有相关考题。