首页/数据结构/线性表/线性表的顺序存储和链式存储 🔗 在 Obsidian 中打开
数据结构 · 线性表

线性表的顺序存储和链式存储

重要度 ⭐⭐ 顺序表链表存储结构时间复杂度
速查
线性表是最基本的线性结构,有两种存储实现:顺序表随机访问 O(1)、存储密度为 1,但增删需移动元素(平均 O(n));链表通过指针链接、增删灵活(已知前驱 O(1)),但只能顺序访问 O(n)

核心概念

线性表是最基本、最简单的数据结构,包含顺序存储链式存储两种实现方式。

顺序表:用一段地址连续的存储单元依次存储线性表的数据元素。逻辑上相邻的元素在物理位置上也相邻,支持随机访问,时间复杂度 O(1)。

链表:用一组任意的存储单元存储线性表的数据元素,通过指针链接各结点。逻辑上相邻的元素在物理位置上不一定相邻,只能顺序访问,时间复杂度 O(n)。

顺序表(连续地址) A B C D 链表(指针链接,地址随意) A B C D
图:顺序表地址连续、支持随机访问;链表用指针把分散的结点串起来、只能顺序访问。

链表的常见变体:

  • 单链表:每个结点含数据域 + 一个指针域
  • 双链表:每个结点含数据域 + 前驱指针 + 后继指针
  • 循环单链表:尾结点指针指向头结点
  • 循环双链表:首尾相连的双链表

关键定义

概念定义
顺序表用数组实现,逻辑相邻则物理相邻,支持随机存取
单链表每个结点包含数据域和一个指向后继的指针域
双链表每个结点包含前驱指针、数据域、后继指针
头结点链表第一个附加结点,数据域可空,简化边界处理
头指针指向链表第一个结点(头结点或首元结点)的指针
循环链表尾结点的指针指向头结点,形成环
头指针 vs 头结点头指针必有(没有头指针找不到链表);头结点可有可无,带头结点可统一空表与非空表的插入/删除操作。

常见考法

考点说明
顺序表与链表的对比从存取方式、空间利用、插入删除效率等维度比较
链表的插入删除操作头插法、尾插法、指定位置插入、删除等指针操作
双链表操作插入/删除需修改四个指针域,常考操作序列
顺序表的插入删除平均移动元素次数:插入 $n/2$,删除 $(n-1)/2$
头结点的作用统一空表和非空表的操作,避免判断头指针是否为空
判空条件顺序表:$length==0$;带头结点单链表:$L\text{->next==NULL}$
最常考顺序表增删的平均移动元素次数是高频计算题:插入平均移动 $n/2$ 个、删除平均移动 $(n-1)/2$ 个元素,均为 O(n)。

易错点

易错清单
  1. 顺序表的下标从 0 开始,但元素位序从 1 开始
  2. 链表插入操作必须先修改新结点的指针,再修改前驱的指针,顺序不能反
  3. 头插法建立的链表元素顺序与输入顺序相反,尾插法顺序相同。
  4. 双链表插入/删除时漏改某个指针会导致链表断裂。
  5. 循环链表判空条件不是 $next==NULL$,而是 $next==$ 头结点。
  6. 顺序表删除元素后需将 length 减 1。

核心结论

  1. 顺序表按位查找时间复杂度 O(1),链表按位查找 O(n)。
  2. 顺序表在表尾插入/删除为 O(1),在表头/中间为 O(n)(需移动元素)。
  3. 链表在已知前驱结点时插入/删除为 O(1),但查找前驱需要 O(n)。
  4. 顺序表存储密度为 1(全部空间用于存储数据),单链表存储密度 < 1。
  5. n 个元素的顺序表,插入操作平均移动 $n/2$ 个元素,删除操作平均移动 $(n-1)/2$ 个元素
  6. 带头结点的单链表,头插法时间复杂度 O(1),尾插法需维护尾指针才可达到 O(1)。
选型口诀表长可预估、查询多 → 顺序表;表长难预估、增删频繁 → 链表。

记忆卡片

顺序表和链表的存取方式区别?
顺序表随机访问 O(1),链表只能顺序访问 O(n)。
顺序表插入/删除的时间复杂度?
平均移动 $n/2$(插入)、$(n-1)/2$(删除),均为 O(n)。
带头结点的好处?
统一空表和非空表的处理,头插法 O(1)。
顺序表与链表的存储密度?
顺序表为 1(全存数据),链表 < 1(含指针域)。

交互动画 · 链表插入与删除的指针修改

head头指针 X新结点 Adata | next Bdata | next Cdata | next Y新结点
带头结点的单链表:head → A → B → C。选择操作查看指针如何修改
点击上方按钮开始
橙色流动虚线表示本次操作新建立/激活的指针路径;灰化的结点表示已脱离链表。插入操作必须先接新结点、再改前驱指针。

相关知识点

stack-and-queue-applications

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。