1. 程式人生 > >資料結構與演算法分析(Java語言描述)(32)—— 使用 Kruskal 演算法求有權圖的最小生成樹

資料結構與演算法分析(Java語言描述)(32)—— 使用 Kruskal 演算法求有權圖的最小生成樹

這裡寫圖片描述

將圖中的所有邊存到最小堆中

當最小堆非空
    取出權重最小的邊
    如果此邊的兩個端點是連線的
        跳出本次迴圈
    將此邊加入 mst 中
    在並查集中 union 此邊的兩端點
package com.dataStructure.weight_graph;

import com.dataStructure.heap.MinHeap;
import com.dataStructure.union_find.UnionFind5;

import java.util.ArrayList;
import java.util.List;

// Kruskal演算法求最小生成樹
public class KruskalMST { private List<Edge> mst; // 存放最小生成樹的邊 private Number mstWeight; // 最小生成樹的權重 // 建構函式 public KruskalMST(WeightedGraph graph) { // 初始化私有欄位 mst = new ArrayList<>(); mstWeight = 0; // 最小堆存放圖中所有的邊 MinHeap<Edge> edgeMinHeap = new
MinHeap<>(graph.E()); for (int i = 0; i < graph.V(); i++) for (Edge edge : graph.adjacentNode(i)) // 遍歷 i 的鄰接節點 if (edge.getV() <= edge.getW()) // 過濾掉 7-1 這種重複的邊 edgeMinHeap.insert(edge); // 將非重複的邊插入最小堆中 // 初始化一個圖中節點數量大小的並查集 UnionFind5 unionFind = new
UnionFind5(graph.V()); // 當最小堆非空 且 最小生成樹尚未連線圖中的所有節點 while (!edgeMinHeap.isEmpty() && mst.size() < graph.V() - 1) { Edge edge = edgeMinHeap.extractMin(); // 取出權重最小的邊 // 如果向 mst 中加入 edge 前,v 和 w 已經連線 // edge 加入 mst 後,將形成環,為防止形成環,跳出此次迴圈 if (unionFind.isConnected(edge.getV(), edge.getW())) continue; mst.add(edge); // 將 edge 加入 mst 中 unionFind.unionElements(edge.getV(), edge.getW()); // 並查集中 union v 和 w } for (Edge edge : mst) // 計算最小生成樹的權重 mstWeight = mstWeight.doubleValue() + edge.getWeight().doubleValue(); } public List<Edge> getMst() { return mst; } public Number getMstWeight() { return mstWeight; } // 測試 Kruskal public static void main(String[] args) { String filename = "/testG1.txt"; int V = 8; SparseGraph g = new SparseGraph(V, false); ReadWeightedGraph readGraph = new ReadWeightedGraph(g, filename); // Test Kruskal System.out.println("Test Kruskal: "); KruskalMST kruskalMST = new KruskalMST(g); List<Edge> mst = kruskalMST.getMst(); for (int i = 0; i < mst.size(); i++) System.out.println(mst.get(i)); System.out.println("The MST weight is: " + kruskalMST.getMstWeight()); System.out.println(); } } //public class KruskalMST { // // private List<Edge> mst; // 最小生成樹所包含的所有邊 // private Number mstWeight; // 最小生成樹的權值 // // // 建構函式, 使用Kruskal演算法計算graph的最小生成樹 // public KruskalMST(WeightedGraph graph) { // mstWeight = 0; // mst = new ArrayList<>(); // // // 將圖中的所有邊存放到一個最小堆中 // MinHeap<Edge> pq = new MinHeap<>(graph.E()); // for (int i = 0; i < graph.V(); i++) // for (Edge edge : graph.adjacentNode(i)) // if (edge.getV() <= edge.getW()) // 過濾掉 7-1 等情況,防止堆中的邊重複 // pq.insert(edge); // // // // 建立一個並查集, 來檢視已經訪問的節點的聯通情況 // UnionFind5 unionFind = new UnionFind5(graph.V()); // while (!pq.isEmpty() && mst.size() < graph.V() - 1) { // // // 從最小堆中依次從小到大取出所有的邊 // Edge e = pq.extractMin(); // // // 如果該邊的兩個端點是聯通的, 說明加入這條邊將產生環, 扔掉這條邊 // if (unionFind.isConnected(e.getV(), e.getW())) // continue; // // // 否則, 將這條邊新增進最小生成樹, 同時標記邊的兩個端點聯通 // mst.add(e); // unionFind.unionElements(e.getV(), e.getW()); // } // // for (Edge edge : mst) // 計算最小生成樹的權重 // mstWeight = mstWeight.doubleValue() + edge.getWeight().doubleValue(); // } // // // 返回最小生成樹的所有邊 // List<Edge> mstEdges() { // return mst; // } // // // 返回最小生成樹的權值 // Number result() { // return mstWeight; // } // // // // 測試 Kruskal // public static void main(String[] args) { // // String filename = "/testG1.txt"; // int V = 8; // // SparseGraph g = new SparseGraph(V, false); // ReadWeightedGraph readGraph = new ReadWeightedGraph(g, filename); // // // Test Kruskal // System.out.println("Test Kruskal:"); // KruskalMST kruskalMST = new KruskalMST(g); // List<Edge> mst = kruskalMST.mstEdges(); // for (int i = 0; i < mst.size(); i++) // System.out.println(mst.get(i)); // System.out.println("The MST weight is: " + kruskalMST.result()); // // System.out.println(); // } //}

這裡寫圖片描述