連通圖最小生成樹的算法及實現

連通圖的最小生成樹java

生成樹定義:node

無向連通圖G的極小連通子圖,稱爲它的生成樹。(n個頂點,n-1條邊)算法

考慮一下下面這個圖數組

上圖是一個徹底圖,它的生成樹不是惟一的,咱們列出最特殊的兩種狀況dom


 

上面2個圖都是第一個徹底圖的生成樹,可是2者是徹底不一樣的。測試

按照深度優先遍歷生成的生成樹,稱爲深度優先生成樹this

按照廣度優先遍歷生成的生成樹,稱爲廣度優先生成樹對象

 

非連通圖的生成森林,概念比較簡單,無非就是非連通圖的極大連通子圖和生成樹的概念疊加排序

 

最小生成樹get

圖G是帶權的無向連通圖,生成樹上個邊權值之和稱爲生成樹的代價,代價最小的生成樹稱爲最小生成樹。

 

最小生成樹的生成算法

Prim算法

現有連通圖G=(V, E),其最小連通圖TG=(TV, TE)。

初始狀態下:V = {V0, V1, V2 ... Vn}; TV = {}

從V當中任選一頂點,插入TV,V = {V0, V1, V2 ... Vn}; TV = {V0}

找鏈接TV和V-TV這兩個集合的權值最小的邊,插入TE,並把該邊2頂點當中本來不屬於TV的頂點加入TV;

重複上一步驟

知道V = TV

 

下面是java實現,首先咱們須要修改一下以前的生成圖的代碼,咱們生成了一棵7個頂點的徹底圖,每一條邊的權值是100之內的隨機數。

        Graph graph = new Graph();
        String nodeNames[] = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg"};
        for (String s : nodeNames) {
            graph.nodes.add(new Node(s));
        }

        graph.arcs = new int[nodeNames.length][nodeNames.length];

        Random ra = new Random();
        for (int i = 0; i < graph.nodes.size(); i ++){
            for (int j = 0; j < graph.nodes.size(); j ++){
                if (i != j){
                    graph.arcs[i][j] = ra.nextInt(100) + 1;
                }
            }
        }

而後是最小生成樹的Prim算法實現,解釋一下,首先建立一個二維數組表示邊,把空間都分配好,只等着往裏面填數就行。而後是一個TreeMap對象,來保存頂點,之因此用TreeMap,是爲了保證新圖的頂點順序和原圖是一致的。剩下的基本就是跟前面算法描述的差很少,你們對着看就行,沒什麼太難的地方。

    public Graph getMinTree(){
        int newArcs[][] = new int[this.nodes.size()][this.nodes.size()];
        Map<Integer, Node> newNodes = new TreeMap<Integer, Node>();

        newNodes.put(0, this.nodes.get(0));

        while(newNodes.size() != this.nodes.size()){
            int minWeight = 99999;
            int minI = -1;
            int minJ = -1;
            for(int i : newNodes.keySet()){
                for (int j = 0; j < this.nodes.size(); j ++){
                    if (i != j && !newNodes.containsKey(j)){
                        if (this.arcs[i][j] < minWeight){
                            minWeight = this.arcs[i][j];
                            minI = i;
                            minJ = j;
                        }
                    }
                }
            }

            newNodes.put(minJ, this.nodes.get(minJ));
            newArcs[minI][minJ] = minWeight;

            newArcs[minJ][minI] = minWeight;
        }

        Graph res = new Graph();
        res.arcs = newArcs;
        res.nodes.addAll(newNodes.values());
        return res;
    }

下面有一次測試的輸出,2個圖,分別是原圖的全部權值信息,另外一個是最小生成樹的權值信息

而後還能夠用連通圖的dfs算法檢查一下。

 

Kruskal算法

先將全部邊按照權值,從小到大排序

依次訪問各邊,若是生成迴路,則捨棄,不然加入生成樹,同時將該邊的另外一頂點加入生成樹

直到全部頂點被加入

java實現,省略。

相關文章
相關標籤/搜索