“有向图中,顶点 $u,v$ 强连通若 $u\leadsto v$ 且 $v\leadsto u$。该关系是等价关系,其等价类称强连通分量(SCC)。把每个 SCC 缩成一个点得到凝聚图,凝聚…”
形式陈述 ​
设图
下表采用这些操作模型:邻接矩阵直接寻址;邻接表的邻居容器为无序序列,且“加边”一栏假设调用者已知该边不存在,或表示本身允许重复记录。若简单图接口必须先防止重边,需先付出
| 表示 | 空间 | 查询边 |
遍历 |
加边 | 删边 |
|---|---|---|---|---|---|
| 邻接矩阵 | |||||
| 邻接表(无序序列) | 摊还 |
||||
| 边集(无索引序列) | 摊还 |
有向图中邻接表通常存出边,遍历入边需另建反向表;带权图把 Boolean 或邻居编号扩展为权值记录;多重图必须允许同一端点对对应多条边或存储重数。
直觉 ​
表示不是算法写完后的存储细节,而是算法能以多大代价看到图。广度优先搜索需要反复枚举当前顶点的邻居:邻接表只触碰实际存在的边,得到
因此“矩阵更快”或“邻接表更省空间”都缺少条件。图的稀疏程度、是否动态修改、是否要遍历入边、是否允许平行边,以及邻居容器本身是数组、哈希集还是有序树,共同决定真实成本。
例子与边界 ​
对道路网络这类稀疏图,
多重图揭示 Boolean 矩阵的边界:两点间两条不同容量的边若都只写成 true,重数和权值都会丢失。可以让矩阵单元存边列表或重数,但此时操作语义与空间分析必须重新说明。自环也要求明确约定:邻接矩阵只占对角线上一个单元,而无向邻接表是存一个表项还是按度数贡献二存两个表项,不同实现皆可,计数公式必须与约定一致。
删除边的成本同样不能脱离容器来写。无序数组需要先找到目标,哈希集合通常提供期望常数时间,有序集合提供对数时间;若允许重复边,还要说明删除一条、全部还是按边标识删除。
推论与应用 ​
DFS、BFS 与强连通分量算法的
从文件或网络读入的边集适合交换与批处理,却通常不是查询阶段的最终索引。常见流程是先接收边记录,再依据下游操作建立恰好需要的表示;若同时维护矩阵和邻接表,就必须承担二者同步更新的不变量。
参考资料
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022,§20.1, representations of graphs。
- Erik D. Demaine and Justin Solomon, MIT 6.006, Graphs, lecture notes,adjacency arrays, adjacency lists, and operation costs。