diff --git a/Data-Structrue/graph.md b/Data-Structrue/graph.md index 7c098d7..d3320b0 100644 --- a/Data-Structrue/graph.md +++ b/Data-Structrue/graph.md @@ -233,4 +233,89 @@ #### 最小生成树定义 -最小生成树也是最小代价树。 \ No newline at end of file +最小生成树MST也是最小代价树。已知生成树就是最小边的能到任意结点的树,这种树只关心边数,所以有多个不同的生成树。 + +而最小生成树就是带权生成树的最小权值和的情况。 + +设R为图G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称G的最小生成树。 + ++ 最小生成树可能有多个,但是边的权值总是唯一且最小的。 ++ 最小生成树的边数=顶点数-1。减去一条则不连通,增加一条则会出现回路。 ++ 若一个连通图本身就是一棵树,则其最小生成树就是其本身。 ++ 只用连通图才有生成树,非连通图只有生成森林。 + +#### Prim算法 + +普里姆算法:从某个顶点开始构建生成树,每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止。 + +时间复杂度为$O(\vert V\vert^2)$,适用于边稠密图。 + +#### Kruskal算法 + +克鲁斯卡尔算法:每次选择一条权值最小的边,使这条边的两头连通,若本就连通的就不选,直到所有的结点都连通。 + +时间复杂度为$O(\vert E\vert\log_2\vert E\vert)$,适用于边稀疏图。 + +### 最短路径 + ++ 单源最短路径:单个结点到图的其他结点的最短路径。 + + BFS算法(无权图)。 + + Dijkstra算法(带权图、无权图)。 ++ 每对顶点间最短路径:每个结点之间的最短路径。 + + Floyd算法(带权图、无权图)。 + +#### BFS算法 + +广度优先算法可以计算无权图的单源最短路径。 + +实际上无权图可以视为一种特殊的带权图,只是每条边的权值全部为1。 + +广度优先算法基本上就是对广度优先遍历的改进。定义两个数组,索引号就代表元素的序号,一个数组表示从起点开始到该点的最短路径长度,另一个数组表示从起点开始到该点的最短路径的上一个结点的索引值。 + +#### Dijkstra算法 + +1. 从$v_0$开始,初始化三个数组:标记各顶点是否已找到最短路径;最短路径长度;最短路径上的前驱。 +2. 遍历所有结点,找到还没确定最短路径,且最短路径长度值最小的的一个顶点,这就确定了下一个最短路径的结点,令其各顶点是否已找到最短路径的值为true。 +3. 检查所有邻接这个结点的其他结点,若其点还没有找到最短路径,则更新最短路径长度值与最短路径上前驱的值。 +4. 重复步骤2再次循环遍历所有结点并找到没确定最短路径则最短路径长度最小的顶点。 + +Dijkstra算法与Prim算法类似,都是优先与最短的路径结合。 + +时间复杂度为$O(\vert V\vert^2)$。 + +当权值中含有负权值的时候可能Dijkstra算法会失效。 + +#### Floyd算法 + +是一种动态规划算法,将问题的求解分为多个阶段。 + +对于n个结点的图G,求任意一对顶点$v_i$到$v_j$之间的最短路径可分为如下阶段: + +1. 初始化:不允许在其他顶点中转,求最短路径。 +2. 若允许在$v_0$中转,求最短路径。 +3. 若允许在$v_0$、$v_1$中转,求最短路径。 +4. ... +5. 若允许在$v_0$、$v_1\cdots v_{n-1}$中转,求最短路径。 + +算法需要遍历n次,每次遍历都需要查看n×n的矩阵中是否有更优的中转点。 + +时间复杂度为$O(\vert V\vert^3)$,空间复杂度为$O(\vert V\vert^2)$。 + +Floyd算法复杂度高,所以基本上都是四个结点以下的图,能解决带负权值的问题,但是不能解决带有负权回路的图,即有负权值的边组成回路,这种图可能没有最短路径。 + +### 有向无环图 + +若一个有向图中不存在环,则是有向无环图,简称DAG图。 + +有向无环图可以运用到表达式的表达上,将操作数共同的结点部分删除并将边合并到一起,这就形成了图。 + +顶点中不可能出现重复的操作数。 + +1. 把各个单个的操作数不重复的排成一排。 +2. 标出各个运算符的生效顺序。 +3. 按顺序加入运算符,并注意对运算符的优先级进行分层。 +4. 当构建完成后从底向上逐层检查同层的运算符是否可以合并。 + +### 拓扑排序 + +AOV网:用DAG图表示一个工程,顶点表示活动,有向边$$表示活动$v_i$必须先于活动$v_j$进行。