無向圖的最短路徑求解算法之——Dijkstra算法

    在準備ACM比賽的過程當中,研究了圖論中一些算法。首先研究的即是最短路的問題。《離散數學》第四版(清華大學出版社)一書中講解的Dijkstra算法是我首先研究的源材料。java

      如何求圖中V0到V5的最短路徑呢?算法

        java實現的方式以下: 數組

       第一步,根據圖來創建權值矩陣:ide

       int[][] W = { 
    {  0,   1,   4,  -1,  -1,  -1 },
    {  1,   0,   2,   7,    5,  -1 },
    {  4,   2,   0,  -1,    1,  -1 },
    { -1,  7,  -1,   0,    3,    2 },
    { -1,  5,    1,   3,   0,    6 },
    { -1, -1,  -1,   2,   6,    0 } };(-1表示兩邊不相鄰,權值無限大)學習

例如:W[0][2]=4 表示點V0到點V2的權值爲4測試

W[0][3]=-1表示點V0與V3不相鄰,因此權值無限大。spa

第二步:對V0標號;V0到其它點的路徑獲得 distance: {0,1,4,-1,-1,-1}; 找到V0到各點中權值最小的那個點(標號的點除外,-1表明無限大),故獲得1即對應的下標1,獲得V1;對V1標號,而後更改V0經過V1到其它點的路徑獲得 distance: { 0, 1, 3, 8, 6, -1}; blog

第三步:找到distance中權值最小的那個點,(標號的點除外)獲得V2,對V2標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 8, 4, -1}; get

第四步:找到distance中權值最小的那個點,(標號的點除外)獲得V4,對V4標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 7, 4, 10}; 數學

第四步:找到distance中權值最小的那個點,(標號的點除外)獲得V3,對V3標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 7, 4, 9}; 

最後只剩下V5沒有被標號,就找到V5了。結束!

源代碼以下:

  
  
           
  
  
  1. package com.xh.Dijkstra;  
  2.  
  3. //這個算法用來解決無向圖中任意兩點的最短路徑  
  4. public class ShortestDistanceOfTwoPoint_V5 {  
  5.     public static int dijkstra(int[][] W1, int start, int end) {  
  6.         boolean[] isLabel = new boolean[W1[0].length];// 是否標號  
  7.         int[] indexs = new int[W1[0].length];// 全部標號的點的下標集合,以標號的前後順序進行存儲,其實是一個以數組表示的棧  
  8.         int i_count = -1;//棧的頂點  
  9.         int[] distance = W1[start].clone();// v0到各點的最短距離的初始值  
  10.         int index = start;// 從初始點開始  
  11.         int presentShortest = 0;//當前臨時最短距離  
  12.  
  13.         indexs[++i_count] = index;// 把已經標號的下標存入下標集中  
  14.         isLabel[index] = true;  
  15.           
  16.         while (i_count<W1[0].length) {  
  17.             // 第一步:標號v0,即w[0][0]找到距離v0最近的點  
  18.  
  19.             int min = Integer.MAX_VALUE;  
  20.             for (int i = 0; i < distance.length; i++) {  
  21.                 if (!isLabel[i] && distance[i] != -1 && i != index) {  
  22.                     // 若是到這個點有邊,而且沒有被標號  
  23.                     if (distance[i] < min) {  
  24.                         min = distance[i];  
  25.                         index = i;// 把下標改成當前下標  
  26.                     }  
  27.                 }  
  28.             }  
  29.             if (index == end) {//已經找到當前點了,就結束程序  
  30.                 break;  
  31.             }  
  32.             isLabel[index] = true;//對點進行標號  
  33.             indexs[++i_count] = index;// 把已經標號的下標存入下標集中  
  34.             if (W1[indexs[i_count - 1]][index] == -1 
  35.                     || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) {  
  36.                 // 若是兩個點沒有直接相連,或者兩個點的路徑大於最短路徑  
  37.                 presentShortest = distance[index];  
  38.             } else {  
  39.                 presentShortest += W1[indexs[i_count - 1]][index];  
  40.             }  
  41.  
  42.             // 第二步:將distance中的距離加入vi  
  43.             for (int i = 0; i < distance.length; i++) {  
  44.                 // 若是vi到那個點有邊,則v0到後面點的距離加  
  45.                 if (distance[i] == -1 && W1[index][i] != -1) {// 若是之前不可達,則如今可達了  
  46.                     distance[i] = presentShortest + W1[index][i];  
  47.                 } else if (W1[index][i] != -1 
  48.                         && presentShortest + W1[index][i] < distance[i]) {  
  49.                     // 若是之前可達,但如今的路徑比之前更短,則更換成更短的路徑  
  50.                     distance[i] = presentShortest + W1[index][i];  
  51.                 }  
  52.  
  53.             }  
  54.         }  
  55.         //若是所有點都遍歷完,則distance中存儲的是開始點到各個點的最短路徑  
  56.         return distance[end] - distance[start];  
  57.     }  
  58.     public static void main(String[] args) {  
  59.         // 創建一個權值矩陣  
  60.         int[][] W1 = { //測試數據1  
  61.                 { 014, -1, -1, -1 },  
  62.                 { 10275, -1 },  
  63.                 { 420, -11, -1 },   
  64.                 { -17, -1032 },  
  65.                 { -151306 },   
  66.                 { -1, -1, -1260 } };  
  67.         int[][] W = { //測試數據2  
  68.                 { 0134 },  
  69.                 { 102, -1 },  
  70.                 { 3205 },  
  71.                 { 4, -150 } };  
  72.  
  73.         System.out.println(dijkstra(W1, 0,4));  
  74.  
  75.     }  
  76. }  

若是須要求無向圖各個點的最短距離矩陣,則屢次運用dijkstra算法就能夠了,代碼以下:

  
  
           
  
  
  1. package com.xh.Dijkstra;  
  2.  
  3. //這個程序用來求得一個圖的最短路徑矩陣  
  4. public class ShortestDistance_V4 {  
  5.     public static int dijkstra(int[][] W1, int start, int end) {  
  6.         boolean[] isLabel = new boolean[W1[0].length];// 是否標號  
  7.         int min = Integer.MAX_VALUE;  
  8.         int[] indexs = new int[W1[0].length];// 全部標號的點的下標集合  
  9.         int i_count = -1;  
  10.         int index = start;// 從初始點開始  
  11.         int presentShortest = 0;  
  12.         int[] distance = W1[start].clone();// v0到各點的最短距離的初始值  
  13.         indexs[++i_count] = index;// 把已經標號的下標存入下標集中  
  14.         isLabel[index] = true;  
  15.         while (true) {  
  16.             // 第一步:標號v0,即w[0][0]找到距離v0最近的點  
  17.  
  18.             min = Integer.MAX_VALUE;  
  19.             for (int i = 0; i < distance.length; i++) {  
  20.                 if (!isLabel[i] && distance[i] != -1 && i != index) {  
  21.                     // 若是到這個點有邊,而且沒有被標號  
  22.                     if (distance[i] < min) {  
  23.                         min = distance[i];  
  24.                         index = i;// 把下標改成當前下標  
  25.                     }  
  26.                 }  
  27.             }  
  28.             if (index == end) {  
  29.                 break;  
  30.             }  
  31.             isLabel[index] = true;  
  32.             indexs[++i_count] = index;// 把已經標號的下標存入下標集中  
  33.             if (W1[indexs[i_count - 1]][index] == -1 
  34.                     || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) {  
  35.                 presentShortest = distance[index];  
  36.             } else {  
  37.                 presentShortest += W1[indexs[i_count - 1]][index];  
  38.             }  
  39.  
  40.             // 第二步:獎distance中的距離加入vi  
  41.             for (int i = 0; i < distance.length; i++) {  
  42.                 // 若是vi到那個點有邊,則v0到後面點的距離加  
  43.                 // 程序到這裏是有問題滴! 呵呵  
  44.                 if (distance[i] == -1 && W1[index][i] != -1) {// 若是之前不可達,則如今可達了  
  45.                     distance[i] = presentShortest + W1[index][i];  
  46.                 } else if (W1[index][i] != -1 
  47.                         && presentShortest + W1[index][i] < distance[i]) {  
  48.                     // 若是之前可達,但如今的路徑比之前更短,則更換成更短的路徑  
  49.                     distance[i] = presentShortest + W1[index][i];  
  50.                 }  
  51.  
  52.             }  
  53.         }  
  54.         return distance[end] - distance[start];  
  55.     }  
  56.    
  57.     public static int[][] getShortestPathMatrix(int[][] W) {  
  58.         int[][] SPM = new int[W.length][W.length];  
  59.         //屢次利用dijkstra算法  
  60.         for (int i = 0; i < W.length; i++) {  
  61.             for (int j = i + 1; j < W.length; j++) {  
  62.                 SPM[i][j] =dijkstra(W, i, j);  
  63.                 SPM[j][i] = SPM[i][j];  
  64.             }  
  65.         }  
  66.         return SPM;  
  67.     }  
  68.  
  69.     public static void main(String[] args) {  
  70.         /* 頂點集:V={v1,v2,……,vn} */ 
  71.         int[][] W = { { 0134 }, { 102, -1 }, { 3205 },  
  72.                 { 4, -150 } };  
  73.         int[][] W1 = { { 014, -1, -1, -1 }, { 10275, -1 },  
  74.                 { 420, -11, -1 }, { -17, -1032 },  
  75.                 { -151306 }, { -1, -1, -1260 } };// 創建一個權值矩陣  
  76.         ;// 創建一個權值矩陣  
  77.         int[][] D = getShortestPathMatrix(W1);  
  78.         //輸出最後的結果  
  79.         for (int i = 0; i < D.length; i++) {  
  80.             for (int j = 0; j < D[i].length; j++) {  
  81.                 System.out.print(D[i][j] + " ");  
  82.             }  
  83.             System.out.println();  
  84.         }  
  85.     }  
  86. }  

若是須要個人學習資料,我很是樂意分享;若是讀者可以有所賜教,我甚感榮幸。QQ:810050504(小帥),郵箱是QQ郵箱

相關文章
相關標籤/搜索