Kruskal算法用于计算一个图的最小生成树。这个算法的过程例如以下:
-
依照边的权重从小到达进行排序
-
依次将每条边添加到最小生成树中,除非这条边会造成回路
实现思路
第一个步骤须要对边进行排序,排序方法在之前的章节中已经介绍了非常多,能够使用优先级队列进行实现,也能够使用归并排序进行实现,这里採用归并排序。
第二个步骤须要推断是否会造成回路。假设添加一条边会形成回路,那么这条边在添加之前,它两端的顶点必然是可以连通的。因此,在算法中使用并查集实现高效的推断。
代码
import java.util.LinkedList; import java.util.Queue; public class KruskalMST { private Queue<Edge> mst = new LinkedList<Edge>(); public KruskalMST(EdgeWeightedGraph G) { // 先对边进行排序 Edge[] edges = new Edge[G.E()]; int i = 0; for (Edge e : G.edges()) { edges[i] = e; i++; } MergeSort.sort(edges); // 使用并查集推断顶点是否连接 UnionFind uf = new UnionFind(G.V()); for (Edge e : edges) { int v = e.either(); int w = e.other(v); if (!uf.connected(v, w)) { uf.union(v, w); mst.add(e); } } } public Iterable<Edge> edges() { return mst; } public double weight() { double result = 0; for (Edge e : mst) { result += e.weight(); } return result; } }
复杂度
上面的代码复杂度和图中边的数量有关,最坏情况下的复杂度为E logE。