最短距離----迪傑斯塔拉演算法----java版
阿新 • • 發佈:2018-11-26
原理(自己理解的,不當之處希望有人可以指出)
圖如上, 以求v0到v8頂點為例
首先求一下v0到各個頂點的距離,得到如下陣列
我們的目的就是根據上面的陣列確定v0到其他各個頂點的最短距離,這樣也就獲得了v0到v8的最短距離.
第一個可以確定最短距離的點
從這個陣列我們可以知道v0到達v1的最短距離肯定是1,但是v0到v2的最短距離卻不一定是5
為什麼這麼肯定呢??????????????
因為與v0直接連通的點就v1和v2這兩個點
那麼v0到v1的最近距離要麼是v0直接到v1的距離:v0-->v1,要麼就是v0-->v2-->[....]-->v1的距離
同理v0到v2的最近距離要麼是v0直接到v2的距離:v0-->v2,要麼就是v0-->v1-->[....]-->v2的距離
由於v0-->v1的距離小於v0-->v2,因此v0直接到v1的距離為v0到v1的直接距離
而對於v0-->v2的距離和v0-->v1-->[....]-->v2的距離並不能得到確定的判斷
由此我們找到了v0到v1的最短距離為1
第二個可以確定最短距離的點
那麼接著我們就從v0--->v1這條路繼續往下走,會得到下圖
由此我們找到了v0到v2的最短距離為4
按照上訴思想,我們就可以找到v0到其他各個點的最短距離,當然假如只是為了找v0到某個點如v4,我們只要是v4這個點的最短距離確定了就可以結束上訴過程.
按照上訴思想我寫的程式碼如下:
package cn.nrsc.graph; /** * @author 孫川 ---- 最短路徑---迪傑斯塔拉演算法(dijkstra) */ public class Graph_Dijkstra { // ----------------------------圖的表示方式------------------------ private int vertexSize;// 頂點的數量 private int[] vertexs;// 頂點對應的陣列 private int[][] matrix;// 鄰接矩陣 private static final int MAX_WEIGHT = 1000;// 代表頂點之間不連通 private boolean[] isVisited; // 頂點是否已經被訪問 public Graph_Dijkstra(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]; } // ----------------------------圖的表示方式------------------------ // 最短距離----迪傑斯塔拉演算法 start--->end之間的最短距離 public void dijkstra(int start, int end) { // 自己到自己的距離為0 if (start == end) { System.out.println(start + "到" + end + "的最短距離為:" + 0); return; } // 首先計算出start到圖中其他各個頂點的距離 int[] distance = new int[vertexSize]; // start到其他各個點的距離 for (int i = 0; i < vertexSize; i++) distance[i] = matrix[start][i]; // 記錄已經確認點的Id,如果是end就可以結束迴圈了 int targetId = 0; // 記錄start到該點是否為最短距離 boolean[] isMinPath = new boolean[vertexSize]; // 到自身的最短距離肯定獲取到了 isMinPath[start] = true; // 迪傑斯塔拉演算法的思想是利用distance陣列確認出start到圖中任意一個點的最短距離 // 一次只能確認start到一個點的最短距離,並且不知道什麼時候會確認了到end點的距離, // 所以我們需要讓他一個點一個點的去確認, 直到end點確認了就可以退出迴圈了 // 最壞的情況下由start到end需要確認的次數是vertexSize-1次 for (int j = 1; j < vertexSize; j++) { // 外層控制確認的次數---最壞情況下為n-1次 int min = MAX_WEIGHT; // 先假設最小距離為MAX_WEIGHT // distance陣列中的最小值為start到它的最短距離 ----- 這裡必須得好好理解一下(看我寫的原理部分) // 找到distance陣列中的最小值 for (int k = 0; k < vertexSize; k++) { if (distance[k] < min && !isMinPath[k]) { min = distance[k]; targetId = k; } } // 確定了start到targetId的最短距離 System.out.println(start + "到" + targetId + "的最短距離為:" + min); // 在是否獲得最短距離陣列中進行標記 isMinPath[targetId] = true; // 如果targetId = end了就說明找到了start到end的最短距離 if (targetId == end) break; // 以min這條路繼續往下走,找到start到不確定點更小的距離----迴圈後,不確定點中的最小值,將可以被確定 for (int w = 0; w < vertexSize; w++) if (!isMinPath[w] && min + matrix[targetId][w] < distance[w]) distance[w] = min + matrix[targetId][w]; } // 列印一下--start到各個點的最短距離 // for (int i = 0; i < vertexSize; i++) // System.out.print(" " + distance[i]); } public static void main(String[] args) { Graph_Dijkstra graph = new Graph_Dijkstra(9); int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT }; int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT }; int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT }; int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT }; int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT }; int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT }; int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 }; int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 }; int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 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; graph.dijkstra(0, 8); System.out.println("---------------------"); graph.dijkstra(8, 0); } }