最小生成樹-----普里姆演算法---java版
阿新 • • 發佈:2018-11-26
最小生成樹(自己理解的,不當之處希望有人可以指出)
簡單的說一下最小生成樹:
假設一個圖,它有n個頂點,則只需n-1條邊,就可以將其組成一個連通圖,在各種組合中,所有n-1條邊的權重之和最小的連通圖,就是所謂的最小生成樹.
演算法思想(自己揣摩的,不當之處希望有人可以指出)
如上圖,我們以v0為起點對整個圖求其最小生成樹,過程如下:
首先既然以v0開始,那麼v0肯定就加入到了最小生成樹中,然後計算v0距離其他各個頂點的距離.不連通的以無窮大表示,則得到vo距離其他各個頂點距離如下:
這代表什麼意思呢?
其實很簡單,就是與v0相連通的點只有v1和v11,而最小生成樹要求v0必須要與圖中其他n-1箇中的某一個點進行連通,且權重值最小,因此很自然而然的我們會讓v0和v1連線起來
按照普里姆演算法的思想既然V0和v1這條邊已經確定了,且v0與其他各個頂點的權重值也知道了,我們這個時候可以繼續考慮一下v1的連通情況及其權重大小 ,同時由於v0和v1已經確定了,我們就先不管他們了,將其值可以都設為0,則:
上圖中得到的這個陣列表示什麼意思呢?其實很好理解,就是v0和v1兩個頂點與其它各個頂點的連通性與權重.
那這個東東有什麼用呢?這時候我們就要有一個整體的思想,為了保證連通性以及權重最小,vo和v1兩個已經確定了的點肯定要與其它的點進行連線,而上面的陣列列出了所有與v0以及v1相連通的點,只要選最小的那個,我們就找到了答案.
重複上面兩個步驟,就得到了滿足要求的最小生成樹.
package cn.nrsc.graph; public class Graph_Prim { // ----------------------------圖的表示方式------------------------ private int vertexSize;// 頂點的數量 private int[] vertexs;// 頂點對應的陣列 private int[][] matrix;// 鄰接矩陣 private static final int MAX_WEIGHT = 1000;// 代表頂點之間不連通 private boolean[] isVisited; // 頂點是否已經被訪問 public Graph_Prim(int vertexSize) { this.vertexSize = vertexSize; this.matrix = new int[vertexSize][vertexSize]; this.vertexs = new int[vertexSize]; for (int i = 0; i < vertexSize; i++) { vertexs[i] = i; } isVisited = new boolean[vertexSize]; } // ----------------------------圖的表示方式------------------------ // 最小生成樹----普里姆演算法 public void prim() { // 假設最先取出頂點0,並遍歷出它與其他所有頂點的距離----正好就是圖中鄰接矩陣的第一行 int[] distance = matrix[0]; int sum = 0; // 總距離 System.out.print("查詢到點的順序:0"); // 控制向樹中新增點的次數 // 因為預設取出了一個點加入到了最小生成樹中,則還需要再確定另外n-1個點的加入順序 for (int i = 1; i < vertexSize; i++) { // 假設初始最小值如下: int min = MAX_WEIGHT; int minId = 0; // 遍歷距離陣列找出該陣列中除了距離為0(說明該點已經加入到了最小生成樹中)和距離為無窮大的 // 所有頂點中距離最小的那個----說明這個點是與已經確定的所有點可以連通,而且值最小 for (int j = 1; j < vertexSize; j++) { if (distance[j] > 0 && distance[j] < MAX_WEIGHT && distance[j] < min) { min = distance[j]; minId = j; } } // 將minId標定為已經確定的點 distance[minId] = 0; System.out.print("--->" + minId); // 計算總距離 sum += min; // 遍歷minId點的所有鄰接點,找到已確定點到其他未知點之間更小的距離 // 0肯定不用再遍歷了,因為第一個確定的點就是它,所以從1開始 for (int k = 1; k < vertexSize; k++) { if (distance[k] > 0 && distance[k] > matrix[minId][k]) { distance[k] = matrix[minId][k]; } } } System.out.println(); System.out.println("最小生成樹的總距離為:" + sum); } // 最小生成樹----普里姆演算法 public static void main(String[] args) { Graph_Prim graph = new Graph_Prim(9); int[] v0 = { 0, 10, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT }; int[] v1 = { 10, 0, 18, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, MAX_WEIGHT, 12 }; int[] v2 = { MAX_WEIGHT, MAX_WEIGHT, 0, 22, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 8 }; int[] v3 = { MAX_WEIGHT, MAX_WEIGHT, 22, 0, 20, MAX_WEIGHT, 24, 16, 21 }; int[] v4 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 20, 0, 26, MAX_WEIGHT, 7, MAX_WEIGHT }; int[] v5 = { 11, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 26, 0, 17, MAX_WEIGHT, MAX_WEIGHT }; int[] v6 = { MAX_WEIGHT, 16, MAX_WEIGHT, 24, MAX_WEIGHT, 17, 0, 19, MAX_WEIGHT }; int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 16, 7, MAX_WEIGHT, 19, 0, MAX_WEIGHT }; int[] v8 = { MAX_WEIGHT, 12, 8, 21, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0 }; graph.matrix[0] = v0; graph.matrix[1] = v1; graph.matrix[2] = v2; graph.matrix[3] = v3; graph.matrix[4] = v4; graph.matrix[5] = v5; graph.matrix[6] = v6; graph.matrix[7] = v7; graph.matrix[8] = v8; //test graph.prim(); } }