經常使用十大算法(六)— 普里姆算法

經常使用十大算法(六)— 普里姆算法

<!-- more -->java

博客說明git

文章所涉及的資料來自互聯網整理和我的總結,意在於我的學習和經驗彙總,若有什麼地方侵權,請聯繫本人刪除,謝謝!

介紹

普利姆(Prim)算法求最小生成樹,也就是在包含n個頂點的連通圖中,找出只有(n-1)條邊包含全部n個頂點的連通子圖,也就是所謂的極小連通子圖github

最小生成樹

  • 最小生成樹(Minimum Cost Spanning Tree),簡稱MST。
  • 給定一個帶權的無向連通圖,如何選取一棵生成樹,使樹上全部邊上權的總和爲最小,這叫最小生成樹
  • N個頂點,必定有N-1條邊
  • 包含所有頂點
  • N-1條邊都在圖中
  • 求最小生成樹的算法主要是普里姆算法和克魯斯卡爾算法

修路問題

image-20200906115427656

  • 有勝利鄉有7個村莊(A, B, C, D, E, F, G) ,如今須要修路把7個村莊連通
  • 各個村莊的距離用邊線表示(權) ,好比 A – B 距離 5千米
  • 問:如何修路保證各個村莊都能連通,而且總的修建公路總里程最短?
  • 思路: 將10條邊,鏈接便可,可是總的里程數不是最小.
  • 正確的思路,就是儘量的選擇少的路線,而且每條路線最小,保證總里程數最少.

思路

  • 設G=(V,E)是連通網,T=(U,D)是最小生成樹,V,U是頂點集合,E,D是邊的集合
  • 若從頂點u開始構造最小生成樹,則從集合V中取出頂點u放入集合U中,標記頂點v的visited[u]=1
  • 若集合U中頂點ui與集合V-U中的頂點vj之間存在邊,則尋找這些邊中權值最小的邊,但不能構成迴路,將頂點vj加入集合U中,將邊(ui,vj)加入集合D中,標記visited[vj]=1
  • 重複步驟②,直到U與V相等,即全部頂點都被標記爲訪問過,此時D中有n-1條邊
代碼實現
package com.atguigu.prim;

import java.util.Arrays;

public class PrimAlgorithm {

    public static void main(String[] args) {
        char[] data = new char[]{'A','B','C','D','E','F','G'};
        int verxs = data.length;
        int [][]weight=new int[][]{
            {10000,5,7,10000,10000,10000,2},
            {5,10000,10000,9,10000,10000,3},
            {7,10000,10000,10000,8,10000,10000},
            {10000,9,10000,10000,10000,4,10000},
            {10000,10000,8,10000,10000,5,4},
            {10000,10000,10000,4,5,10000,6},
            {2,3,10000,10000,4,6,10000},};

        MGraph graph = new MGraph(verxs);
        MinTree minTree = new MinTree();
        minTree.createGraph(graph, verxs, data, weight);
        minTree.showGraph(graph);
        minTree.prim(graph, 1);
    }

}

//最小生成樹
class MinTree {
  //建立
    public void createGraph(MGraph graph, int verxs, char data[], int[][] weight) {
        int i, j;
        for(i = 0; i < verxs; i++) {
            graph.data[i] = data[i];
            for(j = 0; j < verxs; j++) {
                graph.weight[i][j] = weight[i][j];
            }
        }
    }
    
    //顯示
    public void showGraph(MGraph graph) {
        for(int[] link: graph.weight) {
            System.out.println(Arrays.toString(link));
        }
    }
    
    //prim算法
    public void prim(MGraph graph, int v) {
        int visited[] = new int[graph.verxs];
    //標記已訪問
        visited[v] = 1;
        int h1 = -1;
        int h2 = -1;
        int minWeight = 10000;
        for(int k = 1; k < graph.verxs; k++) {
            for(int i = 0; i < graph.verxs; i++) {
                for(int j = 0; j< graph.verxs;j++) {
                    if(visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {
                        minWeight = graph.weight[i][j];
                        h1 = i;
                        h2 = j;
                    }
                }
            }
            System.out.println("邊<" + graph.data[h1] + "," + graph.data[h2] + "> 權值:" + minWeight);
            visited[h2] = 1;
            minWeight = 10000;
        }
    }
}

class MGraph {
    int verxs;
    char[] data;
    int[][] weight;
    
    public MGraph(int verxs) {
        this.verxs = verxs;
        data = new char[verxs];
        weight = new int[verxs][verxs];
    }
}

感謝算法

尚硅谷

以及勤勞的本身,我的博客GitHub微信

微信公衆號

相關文章
相關標籤/搜索