实验报告Prim与Kruskal算法.doc
1.问题
[描述算法问题,首选形式化方式(数学语言),其次才是非形式化方式(日常语言)]
带有权值的图就是网结构。一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小。综合以上两个概念,我们可以得出:构造连通网的最小代价生成树,即最小生成树。
解析
[问题的理解和推导,可用电子版直接在此编写,也可用纸笔推导,拍照嵌入本文档]
对于Prim算法:
假设G=(V,E)为一网图,其中V为顶点的集合,E为边的集合。从某一顶点u1出发选择与它关联的具有最小权值的边(u1, v),将其顶点v加入到生成树顶点,集合U中。U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。
令集合U的初值为U={u1} (假设构造最小生成树时,从顶点u1出发),集合T的初值为T={ }。
以后每一步从U中选择一个顶点u(u属于U),而另一个顶点v属于V-U的边中,选取具有最小权值的边(u,v),将顶点v加入集合U中,将边(u,v)加入集合T中,如此不断重复,直到U=V时,最小生成树构造完毕,这时集合T中包含了最小生成树的所有边。
对于Kruskal算法:
(1)建图,构造Kruskal边集,边集元素应该包括该边的起始顶点、终止顶点、权值;
(2)将边集按权值从小到大的顺序进行排序;
(3)从小到大依次从Kruskal边集中取边加入最小生成树集合,判断条件:将该边加入最小生成树集合,与生成树集合中原有的边不构成环;
(4)最小生成树集合中元素(构成生成树的边)的个数为原图顶点数-1时,代表最小生成树构造完毕。
2.设计
[核心伪代码]
Prim(G)
//构造最小生成树的Prim算法
Vr <— {V。}
Er<— 空集
for i <— 1 to |V| —1 do
在所有的边(v,u)中,求权重最小的边e=(v,u)
使得v在Vr中,而u在V—Vr中,
Vr <—Vr U {u}
Er <—Er U {e*}
return Er
Kruskal(G)
按照边的权重w(ei1)≤…..≤w(wi|E|)的非递减顺序对集合E排序
Er <—空集:ecounter<— 0 //初始化树中边的顶点集合以及集合的规模
k <— 0 //初始化已处理的边的数量
while ecounter < |V|—1 do
k <— k+1
if Er U {eik}无回路
Er <— Er U {er}: ecounter <— ecounter + 1
return Er
3.分析
[算法复杂度推导]
Prim: (|V| - 1+|E|)O(log|V|) = O(|E|log|V|)
Kruskal: O(|E|log|E|)
4.源码
https://github.com/joserfdave/arithmetic/tree/main