1. 程式人生 > 其它 >【演算法4】4.3.6.最小生成樹-Kruskal演算法

【演算法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 操作。

參閱