用Prim算法和Kruskal算法构造最小生成树

用Prim算法和Kruskal算法构造最小生成树

1.问题
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树。

①用Prim算法构造最小生成树:从所有 u∈U,v∈V-U 的边中,选取具有最小权值的边(u,v),将顶点 v 加入集合 U 中,将边(u,v)加入集合 T 中,如此不断重复,直到 U=V 时,最小生成树构造完毕,这时集合 T 中包含了最小生成树的所有边。
②用Kruskal算法构造最小生成树:设无向连通网为 G=(V,E),令 G 的最小生成树为 T,其初态为 T=(V,{}),即开始时,最小生成树 T 由图 G 中的 n 个顶点构成,顶点之间没有一条边,这样 T 中各顶点各自构成一个连通分量。然后,按照边的权值由小到大的顺序,考察 G 的边集 E 中的各条边。若被考察的边的两个顶点属于 T 的两个不同的连通分量,则将此边作为最小生成树的边加入到T 中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当 T 中的连通分量个数为 1 时,此连通分量便为 G 的一棵最小生成树。
2.解析
Prim算法
用Prim算法和Kruskal算法构造最小生成树_第1张图片

Kruskal算法
用Prim算法和Kruskal算法构造最小生成树_第2张图片

[问题的理解和推导,可用电子版直接在此编写,也可用纸笔推导,拍照嵌入本文档]
3.设计
Prim算法:
For(遍历所有点){
Lowcost存储v0与所有相邻边的权值;
adjvex初始化为v0的下标
}
For(遍历所有点i){
While(遍历所有点j)//得点i的所有邻边
{
if(){该边权值最小,min=该权值,k=j}
J++;
}//找到最小权值
Printf(该点中找到的min的边)
Lowcost[k]=0;
重复如上遍历邻接矩阵k行;
(1) 定义min存取最小权值,lowcost[]、adjvex[]分别存权值和顶点下标;
(2) For循环遍历所有与v0相邻的边,并初始化全部顶点为v0下标;
(3) 初始化最小权值为最大的不可能值,遍历全部顶点,找到最小权值;
(4) 打印当前顶点边中权值最小的边,邻接矩阵逐个遍历全部顶点,将较小的权值存入lowcost[],将下标为k的顶点存入adjvex中。

Kruskal算法:
Int sortEdges{
Min=最小权值边;
Key=最小权值边的权值;
While(l //二分法排序按权值将边排序
}
a[]存储所有点
While(遍历所有边){
v1,v2=本次遍历所取边的两个邻接点
If(a[v1]!=a[v2])//不是贿赂
{
Printf(该边)
生成边数增加;
边数大于总边数结束遍历;
}
每次遍历将第一个邻接点替换为第二个,重复遍历以上;
(1)新建图存储所有节点;
(2)将原图中所有的边按权值从小到大排序;
(3)从权值最小的边开始,如果这条边连接的两个节点于图中不在同一个连通分量中,就添加这条边到图中;
(4)循环3,直至图中所有的节点都在同一个连通分量中
4.分析
Prim算法:
设连通网中有 n 个顶点,则第一个进行初始化的循环语句需要执行 n-1 次,第二个循环共执行 n-1 次,内嵌两个循环,其一是在长度为 n 的数组中求最小值,需要执行 n-1 次,其二是调整辅助数组,需要执行 n-1 次,所以,Prim 算法的时间复杂度为O(n2)。
Kruskal算法:
先将图G中的边按代价从小到达排序,则这个操作的时间复杂度为O(elog2e),其中e为无向连通网中边的个数。对于两个顶点是否属于同一个连通分量,可以用并查集的操作将其时间性能提高到O(n),所以Kruskal算法的时间性能是O(elog2e)O(elog2e)。
5.源码
https://github.com/Marvisss/-Prim-Kruskal-

你可能感兴趣的:(用Prim算法和Kruskal算法构造最小生成树)