https://www.hello-algo.com/chapter_graph/graph/#911
图的基本概念
- 图由顶点和边组成,比起链表(线性数据结构)和树(分治结构),图更自由也更复杂
方向性
- 在无向图中,边表示两个顶点之间的双向连接关系,比如微信好友
- 在有向图中,边具有方向性,比如社交网络上的关注和被关注
连通性:连通图connected graph 和 非连通图disconnected graph
- 连通图中,从某个顶点出发,可以到达任意顶点
- 非连通图中,从某个顶点出发,至少有一个顶点无法到达
有权图:为边增加权重,就得到了有权图weighted graph。例如游戏中计算共同游戏时间的亲密度
其他常用术语:
- 「邻接 adjacency」:当两顶点之间存在边相连时,称这两顶点“邻接”。
- 「路径 path」:从顶点 A 到顶点 B 经过的边构成的序列被称为从 A 到 B 的“路径”。
- 「度 degree」:一个顶点拥有的边数。对于有向图,「入度 in-degree」表示有多少条边指向该顶点,「出度 out-degree」表示有多少条边从该顶点指出。
图的表示
1.邻接矩阵表示:以下是一个无向图的邻接矩阵表示例子
它有如下特点:
- 顶点不能和自身相连,所以对角线元素无意义
- 无向图的两个方向等价,所以矩阵关于对角线对称
- 将1替代为权重,即可表示有权图
时间复杂度O(1),空间复杂度O(n^2)
2.邻接表
「邻接表 adjacency list」使用n个链表来表示图,链表节点表示顶点。第i个链表对应顶点i,其中存储了该顶点的所有邻接顶点(与该顶点相连的顶点)
边的数量显然少于n^2,所以邻接表比起矩阵,空间占用较小;但查找效率不如矩阵。
图的常见应用
顶点 | 边 | 图计算问题 | |
---|---|---|---|
社交网络 | 用户 | 好友关系 | 潜在好友推荐 |
地铁 | 站点 | 站点间连通性 | 最短路径问题 |
太阳系 | 星体 | 万有引力作用 | 轨道计算 |
图的基础操作
图的操作分为对顶点和边的操作,邻接矩阵和邻接表的实现各有不同。
基于邻接矩阵的实现
class GraphAdjMat:
"""基于邻接矩阵实现的无向图类"""
def __init__(self, vertices: list[int], edges: list[list[int]]):
"""构造方法"""
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
self.vertices: list[int] = []
# 邻接矩阵,行列索引对应“顶点索引”
self.adj_mat: list[list[int]] = []
# 添加顶点
for val in vertices:
self