【数据结构】图的存储结构:邻接矩阵与邻接表

考点频率 :★★★★☆(选择题常考,是理解图遍历和算法的基础)

难度 :⭐⭐⭐

建议:重点掌握两种存储方式的核心区别(空间复杂度、操作效率),能根据场景判断该用哪种

1️⃣ 为什么需要图的存储结构?

前一篇文章我们学习了图的基本概念------顶点、边、有向图、无向图......但这些都是逻辑结构 。要把图存到计算机里,需要一种具体的物理存储方式

图的存储方式有很多种,软考中最常考的是两种:

  • 邻接矩阵(Adjacency Matrix):用二维数组表示顶点之间的边关系
  • 邻接表(Adjacency List):用数组+链表表示顶点之间的边关系

打个比方 :邻接矩阵像地铁线路的全连接表 ------行和列都是站点,交叉点标记是否连通(1/0),查任意两个站点是否直达非常快,但表格很大。邻接表像每个站点的"出口指示牌"------每个站点只列出它直接连通的其他站点,省空间,但查两个站点是否连通需要翻牌子。

2️⃣ 邻接矩阵(Adjacency Matrix)

2.1 核心思想

用一个 n×nn \times nn×n 的二维数组 AAA 来表示图中 nnn 个顶点之间的边关系。

表示规则

  • 对于无向图 :Aij=1Aij = 1Aij=1 表示顶点 iii 和 jjj 之间有边,否则为 0
  • 对于有向图 :Aij=1Aij = 1Aij=1 表示从顶点 iii 到 jjj 有一条有向边,否则为 0
  • 对于带权图 :Aij=wAij = wAij=w(权值),无连接时用 ∞\infty∞ 表示

2.2 示例

无向图(3个顶点,边:1-2,2-3):

复制代码
邻接矩阵(n=3):
   1  2  3
1  0  1  0
2  1  0  1
3  0  1  0

特点 :无向图的邻接矩阵是对称矩阵 (Aij=AjiAij = AjiAij=Aji)。

有向图(3个顶点,边:1→2,2→3,3→1):

复制代码
邻接矩阵(n=3):
   1  2  3
1  0  1  0
2  0  0  1
3  1  0  0

2.3 邻接矩阵的优缺点

优点 缺点
判断两个顶点之间是否有边 :O(1)O(1)O(1)(直接查矩阵) 空间复杂度 :O(n2)O(n^2)O(n2)(无论图有多少条边,都要 n2n^2n2 空间)
求某个顶点的度 :O(n)O(n)O(n)(统计该行/列中1的个数) 对于稀疏图,浪费大量空间(矩阵中很多0)
实现简单,代码直观 对于带权图 ,需要处理 ∞\infty∞ 值

3️⃣ 邻接表(Adjacency List)

3.1 核心思想

邻接表是一种链式存储 结构。对于图中的每个顶点,用一个链表(或数组)来存储所有与它相邻的顶点

数据结构

  • 表头数组 head[1..n]:每个元素指向一个链表,存储从该顶点出发的所有边

  • 链表节点:存储邻接顶点的编号,以及指向下一个节点的指针

    无向图(3个顶点,边:1-2,2-3):
    head[1] → 2
    head[2] → 1 → 3
    head[3] → 2

3.2 邻接表的优缺点

优点 缺点
空间复杂度 :O(n+e)O(n + e)O(n+e)(eee 为边数),适合稀疏图 判断两个顶点之间是否有边 :O(degree)O(degree)O(degree)(需要遍历链表)
求某个顶点的度 :O(1)O(1)O(1)(对于有向图出度 O(1)O(1)O(1),入度需遍历所有节点或建逆邻接表) 实现比邻接矩阵复杂(需要链表操作)
遍历所有邻接顶点 :O(degree)O(degree)O(degree),效率高 对于稠密图,链表存储指针开销较大

3.3 有向图的邻接表

对于有向图,通常只存储出边

复制代码
有向图(3个顶点,边:1→2,2→3,3→1):
head[1] → 2
head[2] → 3
head[3] → 1

如果需要经常计算入度 ,可以建立逆邻接表(存储指向该顶点的所有顶点)。

4️⃣ 邻接矩阵 vs 邻接表(完整对比表,重点!)

对比项 邻接矩阵 邻接表
空间复杂度 O(n2)O(n^2)O(n2) O(n+e)O(n + e)O(n+e)
判断边是否存在 O(1)O(1)O(1)(直接查) O(degree)O(degree)O(degree)(需遍历链表)
求某顶点的度(无向图) O(n)O(n)O(n)(统计一行) O(1)O(1)O(1)(链表长度)
求某顶点的出度(有向图) O(n)O(n)O(n)(统计一行) O(1)O(1)O(1)(链表长度)
求某顶点的入度(有向图) O(n)O(n)O(n)(统计一列) O(n+e)O(n + e)O(n+e)(需遍历所有链表)
适合图类型 稠密图(边多) 稀疏图(边少)
实现复杂度 简单 较复杂
存储方式 二维数组 数组 + 链表

5️⃣ 如何选择?(软考常考)

场景特征 推荐方式 理由
边数很多(稠密图) 邻接矩阵 矩阵中大部分位置都有值,空间利用率高
边数很少(稀疏图) 邻接表 只存储存在的边,节省空间
需要频繁判断两个顶点之间是否有边 邻接矩阵 O(1)O(1)O(1) 判断,邻接表需要遍历链表
需要频繁遍历某个顶点的所有邻接顶点 邻接表 直接遍历链表,效率高

6️⃣ 经典例题

例题1 :一个有 nnn 个顶点、eee 条边的无向图,若采用邻接表存储,则表头数组的大小为( ),所有链表的节点总数为( )。

A. nnn;2e2e2e

B. nnn;eee

C. n+1n+1n+1;2e2e2e

D. n+1n+1n+1;eee

解析 :无向图中,每条边在邻接表中出现两次 (两个方向各一次),因此链表节点总数为 2e2e2e。表头数组大小为 nnn。选 A


例题2:以下关于邻接矩阵和邻接表的叙述中,正确的是( )。

A. 邻接矩阵适合存储稀疏图

B. 邻接表判断两个顶点之间是否有边的效率高于邻接矩阵

C. 邻接矩阵的空间复杂度为 O(n+e)O(n+e)O(n+e)

D. 邻接表适合存储稀疏图

解析 :A错误------邻接矩阵适合稠密图 ;B错误------邻接矩阵判断边是否存在是 O(1)O(1)O(1),邻接表是 O(degree)O(degree)O(degree),邻接矩阵更快;C错误------邻接矩阵空间复杂度为 O(n2)O(n^2)O(n2)。D正确。选 D


例题3 (判断):在有向图的邻接表中,第 iii 个链表的长度等于顶点 iii 的入度。( )

解析 :错误。在有向图的邻接表中,第 iii 个链表存储的是从顶点 iii 出发 的边,其长度等于顶点 iii 的出度,而不是入度。

7️⃣ 记忆口诀

邻接矩阵二维表,O(1)O(1)O(1) 查边效率高,空间 O(n2)O(n^2)O(n2) 只适稠密图。

邻接表用链表存,只存存在的边,空间 O(n+e)O(n+e)O(n+e) 适合稀疏图。

无向图中边存两次,表头大小就是顶点数。

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

一个有 nnn 个顶点、eee 条边的有向图 ,采用邻接表存储时,所有链表的节点总数为( )。

A. nnn

B. eee

C. 2e2e2e

D. n+en+en+e

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

#软考中级 #软件设计师 #邻接矩阵 #邻接表 #图存储 #数据结构 #软考备考

相关推荐
203号居民2 小时前
LeetCode hot 100 —41. 缺失的第一个正数
数据结构·算法·leetcode
蒸蒸yyyyzwd2 小时前
cpp 选手准备秋招学习笔记 day10
笔记·面试·求职招聘
haerapicom3 小时前
欠定方程里藏着哪几个非零项:OMP 稀疏恢复侦探笔记
笔记
程思扬3 小时前
Android ANR实战排查:主线程SystemClock.sleep导致页面启动偶现无响应
android·笔记
zjnlswd4 小时前
C#学习笔记4
笔记·学习·c#
青山是哪个青山5 小时前
LangChain 学习笔记(九):上下文与记忆
笔记·学习·langchain
2401_862880825 小时前
数据结构 --- 栈
c语言·数据结构·算法
Z5998178416 小时前
c#软件开发学习笔记--Modbus-TCP/UDP网口通讯
笔记·学习·c#
额额额对了7 小时前
数据结构:二叉树
c语言·数据结构·算法