最小生成树☞Prim算法
最小生成树Prim算法:
切分定理
在介绍Prim算法之前,我们现在弄明白两个概念,(横切边与切分定理)
思路分析
因此我们的算法不仅要对每个节点进行标记是否访问过,同时还需要一种数据结构来随时添加元素,并且取出最小边,当然这种数据结构就是堆这种数据结构,下面我们再来一个示例,一步一步分析下
public class LazyPrimMST<Weight extends Number & Comparable >{
/**图的引用*/
private WeightedGraph<Weight> G;
/**标记数组**/
private boolean[] marked;
/**最小堆*/
private MinHeapWeight minHeap;
/**生成最小树所有的边*/
private VectorWeight mst;
/**最小生成树的权值*/
private Number mstWeight;
public LazyPrimMST(WeightedGraph weightedGraph) {
/**初始化操作*/
this.G = weightedGraph;
marked = new boolean[G.V()];
minHeap = new MinHeap(G.E());
mst = new Vector(G.V());
/**从0开始*/
visit(0);
while(!minHeap.isEmpty()){
Edge<Weight> e = minHeap.pop();
/**如果这两条边都被标记过,说明不是一条横切边,则扔掉这条边**/
if(marked[e.a()]==marked[e.b()]){
continue;
}
mst.add(e);
if(!marked[e.a()]){
visit(e.a());
}
else{
visit(e.b());
}
}
/**计算最小生成树的权值*/
mstWeight = mst.get(0).wt();
for(int i=1;i<mst.size();i++){
mstWeight = mstWeight.doubleValue() + mst.get(i).wt().doubleValue();
}
}
private void visit(int i) {
marked[i] = true; //对i节点进行标识
for(Edge<Weight> e: G.adj(i)){
if(!marked[e.getOther(i)]){
minHeap.insert(e);
}
}
}
public VectorWeight>> getMst(){
return mst;
}
/***返回最小生成树的权值*/
public Number getMstWeight(){
return mstWeight;
}
}