邻接矩阵:图的另一种表示方法,优缺点对比

在数据结构中,图是一种由顶点(Vertex)和边(Edge)组成的数据结构。表示图的方法有很多,比如邻接表、邻接矩阵等。其中,邻接矩阵是一种直观且基础的表示方式,尤其适合初学者理解。

一、什么是邻接矩阵?

邻接矩阵本质上是一个二维数组,用于表示图中顶点之间的连接关系。它的核心思想是:用矩阵的行和列分别对应图的顶点,矩阵中的元素值表示两个顶点之间是否存在边,以及边的权重(如果有权重)

1. 基本定义

假设图有 n 个顶点,我们将顶点编号为 0, 1, 2, ..., n-1。邻接矩阵是一个 n×n 的二维数组 adj,其中:
- 若 adj[i][j] = 1(或具体权重值),表示顶点 i 和顶点 j 之间存在一条边;
- 若 adj[i][j] = 0(或无穷大 ),表示顶点 i 和顶点 j 之间不存在边(对于有权图, 表示无直接边)。

2. 示例:无向图的邻接矩阵

假设有一个无向图,顶点为 A, B, C, D(编号 0, 1, 2, 3),边为 A-B, B-C, C-D, D-A。其邻接矩阵如下:

A(0) B(1) C(2) D(3)
A(0) 0 1 0 1
B(1) 1 0 1 0
C(2) 0 1 0 1
D(3) 1 0 1 0
  • 例如:adj[0][1] = 1 表示顶点 AB 之间有边;adj[0][2] = 0 表示 AC 之间没有边。

二、邻接矩阵的优点

  1. 快速判断边是否存在
    要判断顶点 ij 之间是否有边,只需直接访问 adj[i][j],时间复杂度为 O(1)。例如,在邻接表中可能需要遍历链表查找,而邻接矩阵无需遍历,直接通过索引定位。

  2. 计算顶点度高效
    - 无向图:顶点 i 的度(与其他顶点相连的边数)等于邻接矩阵第 i 行的元素之和(因为无向图中边 (i,j) 同时出现在 i 行和 j 列)。
    - 有向图:顶点 i 的出度(从 i 出发的边数)是第 i 行的和,入度(指向 i 的边数)是第 i 列的和。

  3. 适合稠密图
    若图中边数较多(接近 ,即顶点数的平方),邻接矩阵的空间利用率高。例如,一个完全图(任意两个顶点都有边)的邻接矩阵会被完全填满,此时邻接表反而可能因额外存储信息而浪费空间。

  4. 实现简单
    对于初学者,邻接矩阵的数组结构直观易懂,无需复杂的数据结构(如链表或指针),容易理解和编码。

三、邻接矩阵的缺点

  1. 空间效率低
    邻接矩阵需要 n×n 的空间,对于 稀疏图(边数远小于 的图),会造成大量空间浪费。例如,一个有 1000 个顶点、仅 100 条边的稀疏图,邻接矩阵需要 1000×1000 = 1000000 个元素,而邻接表仅需存储 100 条边的信息,空间优势明显。

  2. 遍历邻接顶点效率低
    要遍历顶点 i 的所有邻接顶点,需遍历邻接矩阵的第 i 行(或列),时间复杂度为 O(n)。例如,顶点 A 有 4 个邻接顶点,在邻接矩阵中需要遍历 4 个顶点才能找到所有邻居,而在邻接表中只需直接访问链表即可,时间复杂度为 O(度)(度通常远小于 n)。

  3. 不适合动态调整边数
    当图的边数频繁变化(如插入或删除边)时,邻接矩阵需要修改数组元素,虽然修改单个元素是 O(1),但对于大规模图的动态操作,整体效率仍不如邻接表灵活。

四、总结

邻接矩阵的核心特点是以空间换时间
- 适合场景:稠密图(边数多)、需要频繁查询边是否存在、或计算顶点度的场景。
- 不适合场景:稀疏图(边数少)、需要频繁遍历邻接顶点的场景。

对于初学者而言,邻接矩阵是理解图的基础工具,通过它可以快速掌握图的基本连接关系。但在实际应用中,需根据图的类型(稠密/稀疏)选择合适的表示方法。

小夜