最小生成树
一个有
最小生成树
最小生成树其实是最小权重生成树的简称,一副连通加权无向图中一棵权值最小的生成树。
Kruskal
public class KruskalMST {
private Queue<Edge> mst = new Queue<>();
private double weight;
public KruskalMST(EdgeWeightedGraph g){
MinPQ<Edge> minPQ = new MinPQ<>();
for (Edge edge:g.edges()){
minPQ.insert(edge);
}
UF uf =new UF(minPQ.size());
while (!minPQ.isEmpty()){
Edge edge = minPQ.delMin();
int v = edge.either();
int w = edge.other(v);
if(!uf.connected(v,w)){
uf.union(v,w);
mst.enqueue(edge);
//weight+=edge.weight();
}
}
}
}
Kruskal
算法 基本上取决于优先队列的选择,以及并查集的实现。比较优的算法效率为O(ElogE)
Prim

private Edge[] edgeTo; // edgeTo[v] = shortest edge from tree vertex to non-tree vertex
private double[] distTo; // distTo[v] = weight of shortest such edge
private boolean[] marked; // marked[v] = true if v on tree, false otherwise
private IndexMinPQ<Double> pq;
public PrimMST(EdgeWeightedGraph G){
edgeTo = new Edge[G.V()];
distTo = new double[G.V()];
marked = new boolean[G.V()];
pq = new IndexMinPQ<Double>(G.V());
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
for (int v = 0; v < G.V(); v++) // run from each vertex to find
if (!marked[v]) prim(G, v); // minimum spanning forest
}
private void prim(EdgeWeightedGraph g, int s) {
distTo[s]=0;
pq.insert(s,distTo[s]);
while (!pq.isEmpty()){
grow(g,pq.delMin());
}
}
private void grow(EdgeWeightedGraph g, int v) {
marked[v]=true;
for (Edge e :g.adj(v)){
int w = e.other(v);
if(marked[w]) continue;
if(distTo[w]>e.weight()){
distTo[w]=e.weight();
edgeTo[w] = e;
if(pq.contains(w))
pq.decreaseKey(w,distTo[w]);
else
pq.insert(w,distTo[w]);
}
}
}
Kruskal can have better performance if the edges can be sorted in linear time, or are already sorted。Prim’s better if the number of edges to vertices is high.