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

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

难度 :⭐⭐⭐

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

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

。

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

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

相关推荐
All for pursuit.2 分钟前
【分治-2】215.数组中的第K个最大元素
数据结构·c++·算法·leetcode
lcj25117 分钟前
【C++】set和map——详细使用说明
开发语言·c++·笔记·面试
w_zero_one1 小时前
链表(3)
java·数据结构·算法
Bruce_Liuxiaowei1 小时前
元组与具名元组:把「第 3 个字段」变成「price」
数据结构·python·语法·元组
東隅已逝,桑榆非晚1 小时前
stack和queue(类函数学习和模拟实现)
c++·笔记·学习
LHR_friendship2 小时前
HCIA的相关笔记
笔记·hcia
今晚打老虎12 小时前
c++之提高A(前缀和)(第三课)
数据结构·c++·算法
an123212113 小时前
ARM嵌入式学习笔记:SPI通信协议详解
arm开发·笔记·学习
不会就选b13 小时前
算法日常・每日刷题--<贪心>26
数据结构·算法
Because_of_Her116 小时前
dfs-洪水填充技巧
笔记·算法·深度优先·洪水填充