图论算法深度解析系列
前言:我们为什么要学习图论
在程序员的世界里,图论就像空气般无处不在却常被忽视。从社交网络的好友关系到编译器中的语法分析,从王者荣耀的路径寻找到推荐系统的用户画像,图论算法支撑着现代计算机科学的半壁江山。当你终于理解Dijkstra算法的精妙时,那种顿悟的快感会让你觉得之前的抓耳挠腮都是值得的!
(温馨提示:本文包含大量数学公式和代码示例,建议在电脑端阅读。深呼吸三次,让我们开始这段奇妙旅程)
第一章 图的基本概念
1.1 什么是图
数学上,一个图(Graph) G G G 可以表示为二元组:
G = ( V , E ) G = (V, E) G=(V,E)
其中:
- V V V 是顶点(Vertex)的集合, ∣ V ∣ = n |V| = n ∣V∣=n 表示顶点数
- E E E 是边(Edge)的集合, ∣ E ∣ = m |E| = m ∣E∣=m 表示边数
经典比喻:如果把社交网络看作图,每个人就是顶点,好友关系就是边。微信的好友关系是无向图(互相是好友),微博的关注是有向图(可能单向关注)
1.2 图的分类
类型 | 特点 | 应用场景 |
---|---|---|
无向图 | 边没有方向 | 社交网络、电路板布线 |
有向图 | 边有方向 | 网页链接、任务依赖 |
加权图 | 边带有权重 | 地图导航、网络流量 |
连通图 | 任意两顶点可达 | 通信网络 |
二分图 | 顶点分为两个集合 | 匹配问题、推荐系统 |
1.3 图的度(Degree)
对于顶点 v v v:
- 入度:指向该顶点的边数(有向图)
- 出度:从该顶点出发的边数(有向图)
- 度数:与该顶点相连的边数(无向图)
握手定理:在任意图中,所有顶点的度数之和等于边数的2倍
∑ v ∈ V deg ( v ) = 2 ∣ E ∣ \sum_{v \in V} \deg(v) = 2|E| v∈V∑deg(v)=2∣E∣
第二章 图的存储结构
2.1 邻接矩阵
class Graph:
def __init__(self, num_vertices):
self.matrix = [[0]*num_vertices for _ in range(num_vertices)]
def add_edge(self, u, v, weight=1):
self.matrix[u][v] = weight
# 如果是无向图需要对称赋值
self.matrix[v][u] = weight
时间复杂度:
- 查询是否存在边: O ( 1 ) O(1) O(1)
- 遍历相邻节点: O ( n ) O(n) O(n)
- 空间复杂度: O ( n 2 ) O(n^2) O(n2)
2.2 邻接表
from collections import defaultdict
class Graph:
def __init__(self):
self.adj_list = defaultdict(list)
def add_edge(self, u, v, weight=1):
self.adj_list[u].append((v, weight))
# 无向图需要反向添加
self.adj_list[v].append((u, weight))
时间复杂度:
- 查询是否存在边: O ( d ) O(d)