【数据结构】线性表:链式存储(单链表)

考点频率 :★★★★★(数据结构必考,选择题常与顺序表对比考查)

难度 :⭐⭐⭐

建议:重点理解单链表的节点结构、头指针与头节点的区别,掌握插入/删除操作的时间复杂度

1️⃣ 为什么需要链式存储?

顺序表(数组)虽然支持随机访问,但插入和删除需要移动大量元素,效率很低。如果我们需要频繁进行插入和删除操作,顺序表就不太合适了。

链式存储 应运而生。它的核心思想是:用"指针"把零散的内存块串联起来。逻辑上相邻的元素,物理上不需要相邻,每个元素都"记住"下一个元素的地址。

打个比方 :顺序表就像电影院的一排连座 ,座位号连续,找人快,但有人中途插进来就麻烦(要挪动整排的人)。链表就像寻宝游戏------每个线索纸条上写着下一个线索藏在哪里(地址),你按地址去找,不用管它们是不是在同一个抽屉里。插入新线索时,只需要改两张纸条上的地址就行了。

2️⃣ 单链表的节点结构

单链表的每个节点由两部分组成:

组成部分 含义 作用
数据域(data) 存储数据元素本身 存放实际的数据
指针域(next) 存储下一个节点的地址 指向后继节点,把零散的节点串起来
c 复制代码
// 单链表节点的结构定义(C语言风格伪代码)
typedef struct Node {
    int data;           // 数据域
    struct Node* next;  // 指针域,指向下一个节点
} Node;

3️⃣ 头指针与头节点(关键概念)

这是软考中一个容易混淆的概念,务必分清:

概念 定义 作用
头指针(Head Pointer) 指向链表中第一个节点的指针 是链表的唯一入口,通过它才能找到整个链表
头节点(Head Node) 在第一个数据节点之前额外添加的一个辅助节点 简化插入/删除操作的代码逻辑,避免处理空表等特殊情况

带头节点的单链表结构

复制代码
头指针 → 头节点(数据域为空或存表长) → 第1个数据节点 → 第2个数据节点 → ... → NULL

不带头节点的单链表结构

复制代码
头指针 → 第1个数据节点 → 第2个数据节点 → ... → NULL

软考考点 :在带头节点的单链表中,头指针永远不为空 (即使链表为空,头节点也存在);在不带头节点的单链表中,空链表的头指针为 NULL

4️⃣ 单链表的基本操作与时间复杂度

4.1 查找操作(按值查找 / 按位查找)

按值查找

  • 从第一个数据节点开始,依次比较每个节点的数据域,直到找到目标或遍历结束。
  • 时间复杂度 :O(n)O(n)O(n)(平均需遍历一半节点)

按位查找(获取第 iii 个节点)

  • 从头节点开始,沿着 next 指针逐个向后移动 iii 次。
  • 时间复杂度 :O(n)O(n)O(n)(不支持随机访问,必须从头遍历)

这是链表和数组最显著的区别:链表不支持随机访问,查找必须从头开始。

4.2 插入操作(在第 iii 个位置插入新节点)

带头节点的单链表 为例,在第 iii 个位置插入新节点:

  1. 找到第 i−1i-1i−1 个节点(即插入位置的前驱节点)ppp(从头节点开始遍历)
  2. 将新节点 sss 的 next 指向 ppp 的 next
  3. 将 ppp 的 next 指向 sss
c 复制代码
// 在第 i 个位置插入新节点(带头节点)
s->next = p->next;   // 先连后面
p->next = s;         // 再连前面

时间复杂度分析

  • 查找前驱节点:O(n)O(n)O(n)(需遍历)
  • 插入操作本身(修改指针):O(1)O(1)O(1)
  • 总体时间复杂度 :O(n)O(n)O(n)(主要开销在查找)

特别注意 :如果已经知道插入位置的前驱节点,插入操作本身是 O(1)O(1)O(1)。这是链表相对于顺序表的一大优势------插入不需要移动元素

4.3 删除操作(删除第 iii 个位置的节点)

带头节点的单链表 为例,删除第 iii 个位置的节点:

  1. 找到第 i−1i-1i−1 个节点(即待删除节点的前驱节点)ppp
  2. 用指针 qqq 指向待删除节点:q=p−>nextq = p->nextq=p−>next
  3. 跳过待删除节点:p−>next=q−>nextp->next = q->nextp−>next=q−>next
  4. 释放 qqq 的内存
c 复制代码
// 删除第 i 个节点(带头节点)
q = p->next;         // q 指向待删除节点
p->next = q->next;   // 跳过 q
free(q);             // 释放 q 的内存

时间复杂度分析

  • 查找前驱节点:O(n)O(n)O(n)
  • 删除操作本身(修改指针):O(1)O(1)O(1)
  • 总体时间复杂度 :O(n)O(n)O(n)(主要开销在查找)

5️⃣ 顺序表 vs 单链表(完整对比)

对比维度 顺序表(数组) 单链表
存储方式 连续内存 零散内存(指针链接)
随机访问 ✅ O(1)O(1)O(1) ❌ O(n)O(n)O(n)(必须从头遍历)
按值查找 O(n)O(n)O(n)(无序) O(n)O(n)O(n)
插入(已知位置) ❌ O(n)O(n)O(n)(需移动元素) ✅ O(1)O(1)O(1)(仅修改指针)
插入(未知位置) O(n)O(n)O(n) O(n)O(n)O(n)(需先查找)
删除(已知位置) ❌ O(n)O(n)O(n)(需移动元素) ✅ O(1)O(1)O(1)(仅修改指针)
删除(未知位置) O(n)O(n)O(n) O(n)O(n)O(n)(需先查找)
存储密度 高(1.0,无额外开销) 低(每个节点多存一个指针)
适用场景 查找多、增删少 增删多、查找少

6️⃣ 经典例题

例题1:在带头节点的单链表中,插入一个新节点时,需要修改的指针数量是( )。

A. 0 个

B. 1 个

C. 2 个

D. 3 个

解析 :插入操作需要将前驱节点的 next 指向新节点,同时将新节点的 next 指向后继节点,共修改 2 个指针 。选 C


例题2 :在长度为 nnn 的带头节点的单链表中,删除第 iii(1≤i≤n1 \le i \le n1≤i≤n)个节点,需要遍历的节点个数是( )。

A. iii

B. i−1i-1i−1

C. i+1i+1i+1

D. n−in-in−i

解析 :删除第 iii 个节点需要找到第 i−1i-1i−1 个节点(前驱节点),而从带头节点的链表头开始,需要遍历 iii 个节点才能到达第 i−1i-1i−1 个节点?实际上带头节点中,头节点是第0个,第1个节点是第一个数据节点。找到第 i−1i-1i−1 个数据节点需要从 head 开始移动 i−1i-1i−1 次。更准确地说,要找到第 i−1i-1i−1 个数据节点,需要从头节点开始经过 iii 个节点?不,头节点是第0个,它的 next 指向第1个数据节点。要找第 i−1i-1i−1 个数据节点,需要从头节点开始走 i−1i-1i−1 步。但软考更常见的考法是:删除第 iii 个节点需要找到它的前驱,需定位到第 i−1i-1i−1 个节点,从带头节点的链表头(头节点)开始需要移动 i−1i-1i−1 次。若选项中有 i−1i-1i−1,选它。


例题3(概念判断):单链表支持随机访问,因此可以像数组一样通过下标直接获取任意位置的元素。( )

解析 :错误。单链表不支持随机访问 ,只能从头开始顺序遍历,时间复杂度为 O(n)O(n)O(n)。

7️⃣ 记忆口诀

节点分两段,数据和指针。

头指针定入口,头节点是辅助。

插入删除改指针,不用搬家是优势。

随机访问不支持,查找必须从头走。

8️⃣ 小测验(评论区对答案)

在带头节点的单链表中,若要在第 iii 个节点之前插入一个新节点(i≥1i \ge 1i≥1),需要先找到( )。

A. 第 iii 个节点

B. 第 i−1i-1i−1 个节点

C. 第 i+1i+1i+1 个节点

D. 头节点

🔔 本专栏日更,点击头像 → 专栏《软考中级高频考点》订阅,第一时间接收新内容

#软考中级 #软件设计师 #单链表 #链式存储 #线性表 #数据结构 #软考备考

相关推荐
今天AI了吗1 小时前
精细化落地教程:TimechoAI调参标准+数据清洗规范+误差归因+阈值适配全维度指南
大数据·人工智能·算法
zephyr052 小时前
从递归到迭代:二叉树非递归前中后序遍历详解
算法
Dr.kangder2 小时前
嵌入式总线设备解析——TTE总线应用与实践
开发语言·网络·算法·嵌入式·多任务·同步机制
Hi李耶2 小时前
【LeetCode】557.反转字符串中的单词 III
算法·leetcode·职场和发展
yyy(十一月限定版)2 小时前
016【入门】双端队列
数据结构·c++
深蓝学院2 小时前
机器人学习算法五大体系详解:模仿、强化、多模态、持续学习……
算法·机器人
白狐_7983 小时前
408数据结构:中缀转后缀与操作符栈容量——真题精讲
前端·javascript·数据结构
2401_858286113 小时前
OS82.【Linux】设计线程池
java·linux·运维·服务器·开发语言·算法·线程池
Epiphany.5563 小时前
找到所有好字符串(记忆化搜索+KMP)(里面含KMP模板,用来入门)
算法
疯狂打码的少年3 小时前
【数据结构】链表变体:双向链表与循环链表
数据结构·笔记·链表