1. 问题
举实例,分别画出采用Prim算法和Kruskal算法构造最小生成树的过程,并实现代码。
2. 解析
生活中最小生成树问题的应用很广泛,例如有四个村庄要修四条路,让村子能两两联系起来,这时就有最优的问题,怎样修才是做好的。可以采用Prim算法或Kruskal算法解决。
**最小生成树:**一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。
**Prim算法:**通过一系列不断扩张的子树来构造一棵最小生成树。如图,从图的顶点集合中选择“1”顶点作为序列中的初始子树,每次迭代把不在树中的最近顶点添加到树中(它以一条权重最小的边和树中的顶点相连),直至树覆盖了图中的所有结点。
**Kruskal算法:**把一个加权连通图G=<V, E>的最小生成树看作一个具有|V|-1条边的无环子图,并且边的权重和是最小的。令图的初始状态为|V|个结点而无边的非连通图,图中的每个顶点自成一个连通分量。接着,每次从图G中所有两个端点落在不同连通分量的边中,选取权重最小的那条,将该边加入图中,如此往复,直至图中所有顶点都在同一个连通分量上。
3. 设计
Prim算法:
输入:图G=(V,E,W),V={1,2,…,N}
初始S={1}.
选择连接S与V-S集合的最短边e={i,j},其中i∈S,j∈V-S,将e加入树T,j加入S.
继续执行上述过程,直到S=V.
运行结果:
Kruskal算法:
输入:图G=(V,E,W),V={1,2,…,N}
将边按照长度从小到大排序.
依次考察当前最短边e,如果e与T的边不构成回路,则把e加入到树T中,否则跳过e.
执行上述过程,直至选择了n-1条边为止.
运行结果:
4. 分析
Prim算法:T(n) = O(n^2)
Kruskal算法:T(n) = O(nlogn)
5. 源码
https://github.com/LiChunning/The-Design-and-Analysis-of-Algorithms/blob/main/prim.cpp
https://github.com/LiChunning/The-Design-and-Analysis-of-Algorithms/blob/main/kruskal.cpp