图
- 一、图的基本概念
- 1.1 图的定义
- 1.2 顶点的度、入度、出度
- 1.3 顶点 - 顶点的关系描述
- 1.4 子图 、连通分量
- 1.5 特殊形态的图
- 1.6 总结
- 二、图的存储
- 2.1 邻接矩阵法
- 2.1.1 如何根据邻接矩阵求度
- 2.1.2 邻接矩阵存储带权图(网)
- 2.1.3 邻接矩阵法的性能分析
- 2.1.4 邻接矩阵法的性质
- 2.2 邻接表法 (顺序 + 链式存储)
- 2.2.1 求顶点的度
- 2.2.2 邻接表 邻接矩阵对比
- 2.3 十字链表法存储有向图
- 2.4 邻接多重表存储无向图
- 2.5 总结
- 三、图的基本操作
- 四、图的遍历算法
- 4.1 广度优先遍历 BFS
- 4.1.1 代码实现
- 4.1.2 存在问题 & 最终版
- 4.1.3 复杂度分析
- 4.1.4 广度优先生成树
- 4.1.5 广度优先生成森林
- 4.1.6 总结
- 4.2 深度优先遍历 DFS
- 4.2.1 代码
- 4.2.2 存在问题 & 最终版
- 4.2.3 复杂度分析
- 4.2.4 示例
- 4.2.5 深度优先生成树
- 4.2.6 图的遍历与图的连通性
- 4.2.7 总结
- 五、最小生成树
- 5.1 定义
- 5.2 Prim 算法
- 5.2.1 算法思想
- 5.2.2 实现思想
- 5.2.3 复杂度
- 5.3 Kruskal 算法(克鲁斯卡尔)
- 5.3.1 算法思想
- 5.3.2 实现思想
- 5.3.3 复杂度
- 5.4 Prim 算法 & Kruskal算法 对比
- 六、最短路径问题
- 6.1 BFS求无权图的单源最短路径
- 6.2 DIjkstra 算法 ---O(n2)
- 6.2.1 基本思想
- 6.2.2 实现过程
- 6.2.3 复杂度
- 6.3 Floyd算法 ---O(n3)
- 七、有向无环图(DAG)
- 7.1 DAG描述表达式解题方法:
- 7.2 拓扑排序
- 7.2.1 拓扑排序实现方法
- 7.2.2 代码实现
- 7.3 逆拓扑排序
- 7.4 总结
- 八、关键路径
- 8.1 AOE 网
- 8.2 求关键路径的步骤
- 8.3 关键活动、关键路径的特性
- 8.4 总结
一、图的基本概念
1.1 图的定义
由顶点集V和边集E组成,记为 G = (V , E)
若V={v1,v2,v3…},则用 | V | 表示图G中顶点的个数,也称图G的阶
E = { ( u , v ) | u ∈ \in ∈V,v ∈ \in ∈V} ,用 | E | 表示图G中的边的条数
注意: V一定是非空集 ( 线性表可以是空表、树可以是空树、图不可以为空 )
- 无向图
若E是无向边的有限集合时,图G为五向边,边是顶点的无序对,记为 (v,w)或(w,v)
(v,w)=(w,v)
- 有向图
若E是有向边(也称弧)的有限集合时,图G为有向图,边是顶点的有序对,记为 ,v称为弧尾,w称为弧头
表示从顶点v到顶点w的弧
!=
- 简单图 和 多重图
1.2 顶点的度、入度、出度
- 无向图
顶点v的度是指依附于该顶点的边的条数,记为 TD(v)
无向图的全部顶点的度的和等于边数的2倍:总度数 = 2e
- 有向图
入度:以顶点v为终点的有向边的数目
出度:以顶点v为起点的有向边的数目
顶点v的度等于入度 和 出度之和
在具有n个顶点、e条边的有向图中,总入度数 = 总出度数 = e
1.3 顶点 - 顶点的关系描述
-
路径:顶点Vp到顶点Vq之间的一条路径是指顶点序列:Vp,V1,V2…Vq
-
回路:第一个顶点和最后一个顶点相同的路径称为回路或环
-
简单路径:在路径序列中,顶点不重复出现的路径称为简单路径
-
简单回路:除第一个顶点和最后一个顶点外,其余顶点不重复出现的回路
-
路径长度:路径上边的数目、
-
点到点的距离:从顶点u出发到顶点v的最短路径若存在,则此路径长度称为u到v的距离,若不存在,则记为 ∞ \infty ∞
-
无向图中,从顶点v到顶点w有路径存在,则称为v和w是连通的
-
有向图中,从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通的
-
无向图中,若任意两个顶点都是连通的,则称为连通图 否则非连通图
考点: 对于n个顶点的无向图G,若G是连通图 则最少有n-1条边 若G是非连通图 最多可能有 C2n-1 条边
-
有向图中,若任意一对顶点都是强连通的,则称为强连通图
考点:对于n个顶点的有向图G,若G是强连通图 则最少有n条边
1.4 子图 、连通分量
1. 子图:
2. 连通分量
1.5 特殊形态的图
- 无向完全图
无向完全图共有C2n条边
- 有向完全图
无向完全图共有2C2n条边
- 稀疏图 和 稠密图
- 树、有向树
1.6 总结
二、图的存储
2.1 邻接矩阵法
数组实现的顺序存储,空间复杂度高 不适合存储稀疏图
0表示两个点之间不连通
1表示两个点之间连通
2.1.1 如何根据邻接矩阵求度
- 无向图
第i个结点的度 = 第i行(或者第i列)的非零元素个数
时间复杂度:O(n)
- 有向图
第 i 个结点的出度 = 第 i 行的非零元素的个数
第 i 个结点的入度 = 第 i 列 的非零元素个数
第 i 个结点的度 = 第 i 行、第 i 列 的非零元素个数之和
时间复杂度:O(n)
2.1.2 邻接矩阵存储带权图(网)
2.1.3 邻接矩阵法的性能分析
空间复杂度 : O(|v|2) —只和顶点数相关 和 实际边数无关
适用于i存储稠密图
无向图的邻接矩阵式对称矩阵,可以压缩存储
2.1.4 邻接矩阵法的性质
- 设图G的邻接矩阵为A(矩阵元素为0/1),则An[ i ] [ j ] 等于由顶点 i 到 顶点 j 的长度为 n 的路径的数目
2.2 邻接表法 (顺序 + 链式存储)
2.2.1 求顶点的度
- 无向图 : 直接遍历每个点指向的单链表
- 有向图:找出度同无向图 但是入度不方便找
2.2.2 邻接表 邻接矩阵对比
2.3 十字链表法存储有向图
2.4 邻接多重表存储无向图
2.5 总结
三、图的基本操作
- Adjacent ( G , x , y ) : 判断图G是否存在边或者(x,y)
- Neighbors(G,x) : 列出图G中与结点x邻接的边
- INsertVertex(G,x): 在图G中插入顶点x
- DeleteVertex(G,x): 从图G中删除顶点x
- AddEdge(G,x,y):若无向边(x,y)或者有向边不存在,则向图G中添加该边
- FirstNeighbor(G,x): 求图G中顶点x的第一个邻接点,若有则返回顶点号,若x没有邻接点或者图中不存在x,则返回-1
- NextNeighbor(G,x,y): 假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
- Get_edge_value(G,x,y):获取图G中边(x,y)或者对应的权值
- Set_edge_value(G,x,y):设置图G中边(x,y)或者对应的权值v
四、图的遍历算法
4.1 广度优先遍历 BFS
4.1.1 代码实现
注意:
同一个图的邻接矩阵表示方式唯一,因此广度优先遍历唯一
同一个图的邻接表表示方式不唯一,因此广度优先遍历不唯一
4.1.2 存在问题 & 最终版
问题:若是非连通图 ,则无法遍历完所有节点
对于无向图,调用BFS函数的次数 = 连=连通分量的个数
4.1.3 复杂度分析
4.1.4 广度优先生成树
4.1.5 广度优先生成森林
4.1.6 总结
4.2 深度优先遍历 DFS
4.2.1 代码
类似于树的先根遍历
4.2.2 存在问题 & 最终版
若是非连通图 则无法遍历完所有节点
4.2.3 复杂度分析
- 空间复杂度:
- 时间复杂度:
4.2.4 示例
4.2.5 深度优先生成树
4.2.6 图的遍历与图的连通性
4.2.7 总结
五、最小生成树
5.1 定义
对于一个带权连通无向图 G = ( V , E ) ,生成树不同,每棵树的权(即树中所有边的权值之和)可能不同
权值之和最小的一颗生成树称为最小生成树
同一个图可能有多个最小生成树
注意:
- 若一个连通图本身就是一棵树,则最小生成树就是本身
- 只有连通图才有生成树,非连通图只有生成森林
5.2 Prim 算法
5.2.1 算法思想
从某一个顶点开始构建生成树,每次将代价最小的新顶点纳入生成树,直到所有顶点全部纳入为止
5.2.2 实现思想
**
5.2.3 复杂度
5.3 Kruskal 算法(克鲁斯卡尔)
5.3.1 算法思想
每次选择一条权值最小的边,使这条边的两头连通(原本连通的不用选)
直到所有节点都连通
5.3.2 实现思想
5.3.3 复杂度
5.4 Prim 算法 & Kruskal算法 对比
六、最短路径问题
- 单源最短路问题: 一个点到其他点最短路径
- 多源最短路问题:任意两个点的最短路径
6.1 BFS求无权图的单源最短路径
BFS局限性:
- 只适用于不带权值的图
- 或者是所有边的权值都相同的图
6.2 DIjkstra 算法 —O(n2)
6.2.1 基本思想
对图G(V,E)设置集合S,存放已被访问的顶点,然后每次从集合V-S中选择与起点s的最短距离最小的顶点u,访问并加入S,然后以u为中介点,更新起点s与所有从u能到达的顶点v之间的最短距离 直到S已经包含所有顶点
Dijkstra不适用与带负权值的带权图
只用于带正权
操作步骤:
- 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为”起点s到该顶点的距离” [ 例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为 ∞ \infin ∞ ]。
- 从U中选出”距离最短的顶点k”,并将顶点k加入到S中;同时,从U中移除顶点k。
- 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
- 重复步骤(2)和(3),直到遍历完所有顶点。
6.2.2 实现过程
6.2.3 复杂度
6.3 Floyd算法 —O(n3)
用于求解各个顶点之间的最短路径
可以解决带有负权的图
但是不能有回路
6.3.1 核心代码
七、有向无环图(DAG)
定义:若一个有向图中不存在环,则称为有向无环图
7.1 DAG描述表达式解题方法:
- 把各个操作数不重复的排成一排
- 标出各个运算符的生效顺序(先后顺序有点出入无所谓)
- 按顺序加入运算符,注意分层
- 从底向上逐层检查同层的运算符是否可以合体
7.2 拓扑排序
AOV网一定是有向无环图 —无回路
7.2.1 拓扑排序实现方法
- 从AOV网中选择一个没有前驱(入度为0)的顶点并输出
- 从网中删除该顶点和所有以它为起点的有向边
- 重复 1 和 2直到当前的AOV网为空 或者 当前网中不存在无前驱的顶点为止
拓扑排序满足的条件:
- 每个顶点出现且只出现一次
- 若顶点A在序列中排到顶点B的前面,则在图中不存在从顶点B到顶点A的路径
每个AOV网都有一个或者多个拓扑排序序列
一个有向无环图一定至少存在一个入度为0的点
7.2.2 代码实现
时间复杂度:O(V+E)
若采用邻接矩阵:O(V2)
7.3 逆拓扑排序
7.3.1 逆拓扑排序 DFS实现
7.4 总结
八、关键路径
8.1 AOE 网
在带权有向图中,以顶点表示事件,以有向边表示活动,以边上的权值表示完成该活动的开销,称之为用边表示活动的网络 AOE网
8.2 求关键路径的步骤
8.3 关键活动、关键路径的特性
- 若关键活动耗时增加,则整个工程的工期将增长
- 缩短关键活动的时间,可以缩短整个工程的工期
- 当缩短到一定程度时,关键活动可能会变成非关键活动
- 可能有多条关键路径,只提高一条关键路径上的关键活动速度并不能缩短整个工程的工期,只有加快那些包括在所有关键路径上的关键活动才能缩短工期
8.4 总结