【算法4】4.3.6.最小生成树-Kruskal算法

Kruskal算法(又称克鲁斯卡尔算法)。

其思想是:首先将图看成是由一个个孤立的顶点组成,然后按边的权重从小到大处理,将顶点连接起来,
并且要保证选取的边不会跟已选取的边构成环,当选出 V - 1 条边时最小生成树生成完成。

Kruskal 算法每次选取出最小的横切边(横切边就是连接最小生成树及其补集的边),是贪心算法的体现。

Kruskal 算法实现:

  • 使用优先队列将边按从小到大的顺序弹出
  • 使用 union-find 算法 判断是否有环产生
  • 使用队列来保存最小生成树的边
/**
 * 使用克鲁斯卡尔算法找出加权连通图的最小生成树
 * */
public class KruskalMST implements MST {
    private Queue<Edge> mst;

    public KruskalMST(EdgeWeightedGraph G) {
        mst = new Queue<>(); // 使用优先队列保存最小生成树的边
        MinPQ<Edge> pq = new MinPQ<>(); // 使用优先队列按边从小到大顺序处理
        UnionFind unionFind = new UnionFind(G.V()); // 使用 union-find 算法检测是否会产生环

        // 将所有边添加到优先队列
        for (Edge e : G.edges()) {
            pq.add(e);
        }

        // 开始生成最小生成树
        while (!pq.isEmpty() && mst.size() < G.V() - 1) {
            Edge e = pq.remove();
            int v = e.either();
            int w = e.other(v);
            if (unionFind.connected(v, w)) {
                continue;
            }
            mst.add(e);
            unionFind.union(v, w);
        }
    }
}

性能分析:Kruskal 算法一般比 Prim 算法慢,因为在处理每条边时除了两种算法都要完成优先队列操作之外,Kruskal 算法还需要进行一次 union-find 操作。

参阅

posted @ 2022-06-05 21:34  廖子博  阅读(59)  评论(0编辑  收藏  举报