📊 一、图的基本概念
1. 图的定义
-
图由顶点集V 和边集E组成,记为 G=(V,E)。
-
顶点数 ∣V∣称为图的阶,边数记为 ∣E∣。
-
图比线性表(一对一)和树(一对多)更复杂,元素间是多对多关系。
2. 有向图与无向图
-
无向图:边无方向,可视为双向的有向图。
-
有向图:边有方向,需区分入度和出度。
3. 简单图与多重图
-
简单图:无自环(顶点到自身的边)和重边(重复边)。
-
多重图:允许自环或重边。
4. 稠密图与稀疏图
- 边数 e<nlogn时为稀疏图 ,反之为稠密图。
5. 顶点的度
-
无向图:度 = 入度 = 出度,即 deg(v)=indeg(v)=outdeg(v)。
-
有向图:度 = 入度 + 出度。
6. 路径与回路
-
路径:顶点序列 (vi,vp1,...,vj)。
-
简单路径:顶点不重复。
-
回路:起点与终点相同的路径。
7. 路径长度
-
无权图:路径长度为边数。
-
带权图(网络):路径长度为边权之和。
8. 子图与生成子图
-
子图:从原图中选取部分顶点和边。
-
生成子图:包含原图所有顶点的子图。
9. 连通图与连通分量
-
连通图:任意两点间有路径。
-
连通分量:无向图中的极大连通子图。
-
若边数 < n−1,则图必不连通。
10. 生成树
-
包含所有顶点的极小连通子图,边数为 n−1。
-
删除任一边会破坏连通性,添加任一边会形成环。
🗂️ 二、图的存储与遍历
1. 存储方式
-
邻接矩阵:二维数组存储边权,空间复杂度 O(n2),适合稠密图。
-
邻接表(vector数组/链式前向星):存储每个顶点的邻接点,空间复杂度 O(n+m),适合稀疏图。
2. 遍历算法
-
DFS(深度优先搜索):递归或栈实现,一条路径深入到底。
-
BFS(广度优先搜索):队列实现,按层遍历。
🌳 三、最小生成树(MST)
1. Prim算法
-
贪心策略:从任意顶点开始,每次添加距离当前树最近的顶点。
-
适合稠密图,时间复杂度 O(n2)或 O(mlogn)(堆优化)。
2. Kruskal算法
-
贪心策略:按边权排序,每次选择不形成环的最小边。
-
适合稀疏图,时间复杂度 O(mlogm),需用并查集判环。
🔁 四、拓扑排序
-
适用条件:有向无环图(DAG)。
-
AOV网:顶点表示活动,边表示依赖关系。
-
算法流程:
-
入度为0的顶点入队。
-
出队并删除其出边,更新邻接点入度。
-
重复直至队列空。
-
-
若未处理所有顶点,说明存在环。
🛣️ 五、最短路径
1. Dijkstra算法
-
贪心策略:适用于非负权图。
-
每次选择未确定最短路径中距离起点最近的点,更新邻接点。
-
时间复杂度:O(n2)或 O(mlogn)(堆优化)。
2. Bellman-Ford算法
-
动态规划思想:松弛所有边 n−1轮。
-
可处理负权边,判断负环(第 n轮仍可松弛则存在负环)。
-
时间复杂度 O(nm)。
3. SPFA算法
-
队列优化BF算法:仅对可能松弛的点操作。
-
最坏时间复杂度 O(nm),平均效率较高。
4. Floyd算法
-
动态规划:求任意两点间最短路径。
-
状态转移:f[k][i][j]=min(f[k−1][i][j],f[k−1][i][k]+f[k−1][k][j])。
-
时间复杂度 O(n3),适合稠密图。
💡 核心总结
-
图的结构灵活,可建模复杂关系。
-
存储与遍历是基础,DFS/BFS需熟练掌握。
-
最小生成树 与最短路径是经典问题,需根据图特性选择算法。
-
拓扑排序 用于DAG的依赖解析,负环判断是关键难点。
-
实际应用中需结合问题规模、边权正负、稠密性等因素选择算法。