1. 程式人生 > >最短路問題之Dijkstra算法

最短路問題之Dijkstra算法

鄰居 距離 我們 contain dijkstra info -s static 數組

題目:

  在上一篇博客的基礎上,這是另一種方法求最短路徑的問題。

  Dijkstra(迪傑斯特拉)算法:找到最短距離已經確定的點,從它出發更新相鄰頂點的最短距離。此後不再關心前面已經確定的“最短距離已經確定的點”。

  Dijkstra算法采用的是一種貪心的策略,聲明一個數組dis來保存源點到各個頂點的最短距離和一個保存已經找到了最短路徑的頂點的集合:T,初始時,原點 s 的路徑權重被賦為 0 (dis[s] = 0)。若對於頂點 s 存在能直接到達的邊(s,m),則把dis[m]設為w(s, m),同時把所有其他(s不能直接到達的)頂點的路徑長度設為無窮大。

  初始時,集合T只有頂點s。然後,從dis數組選擇最小值,則該值就是源點s到該值對應的頂點的最短路徑,並且把該點加入到T中,OK,此時完成一個頂點,然後,我們需要看看新加入的頂點是否可以到達其他頂點並且看看通過該頂點到達其他點的路徑長度是否比源點直接到達短,如果是,那麽就替換這些頂點在dis中的值。然後,又從dis中找出最小值,重復上述動作,直到T中包含了圖的所有頂點。

代碼:

  1 import java.util.HashSet;
  2 import java.util.Set;
  3 
  4 public class 圖的最短路問題_Dijkstra {
  5     public static void main(String[] args) {
  6         int s = 1;
  7         int[] shortestPath = shortestPath(s);
  8 
  9         for (int i = 0; i < prev.length; i++) {
 10             System.out.println((char
) (‘A‘ + s) + "到" + (char) (‘A‘ + i) + "的路徑"); 11 System.out.print((char) (‘A‘ + i) + "<-"); 12 int j = prev[i]; 13 while (j != s) { 14 System.out.print((char) (‘A‘ + j) + "<-"); 15 j = prev[j]; 16 } 17
System.out.print((char) (‘A‘ + j)); 18 System.out.println(":" + shortestPath[i]); 19 } 20 } 21 22 static int[] prev; 23 24 /** 25 * 求起點到各頂點的最短距離 26 * 27 * @param s 起點 28 * @return 29 */ 30 private static int[] shortestPath(int s) { 31 // 頂點個數 32 int n = graph.length; 33 // 記錄每個點的前驅 34 prev = new int[n]; 35 // 一定要初始化,源點的前驅是自身 36 prev[s] = s; 37 // 記錄s到各頂點的最短距離 38 int[] d = new int[n]; 39 d[s] = 0;// 自己到自己的距離為0 40 // 記錄已經找到最短距離的頂點 41 Set<Integer> T = new HashSet<>(); 42 T.add(s); 43 44 /*-第一步:直接可達的頂點,用距離來初始化d,d[s]=0,可直達的把距離記錄下來作為待定值-*/ 45 for (int i = 0; i < n; i++) { 46 if (i != s && graph[s][i] == 0) 47 d[i] = Integer.MAX_VALUE;// 不可直達的頂點,先以最大整數作為待定值 48 if (i != s && graph[s][i] > 0) { 49 d[i] = graph[s][i]; // 可直達的頂點,以直達距離作為待定值 50 prev[i] = s; // 可直達的頂點,其前驅是源點 51 } 52 } 53 // Util.print(d); 54 55 while (T.size() < n) { 56 /*-第二步:從待定的距離表中找到最小值,這個值可以作為確定值,為什麽?-*/ 57 int min = minIndex(d, T); 58 T.add(min); 59 if (T.size() == n) 60 break; 61 /*-第三步,看這個新確定的頂點的出度,看看從源點出發是經過這個頂點到其鄰居近還是直達更近,如果更近就要更新-*/ 62 // 掃描index的鄰居 63 for (int neighbor = 0; neighbor < n; neighbor++) { 64 int cost = graph[min][neighbor]; 65 // 更新 66 if (cost > 0 && d[neighbor] > d[min] + cost) { 67 d[neighbor] = d[min] + cost; 68 prev[neighbor] = min; // 更新最短路後,要更新i這個點的前驅 69 } 70 } 71 } 72 return d; 73 } 74 75 /** 76 * 從未確定的點裏面找一個最小的 77 * 78 * @param d 79 * @param t 已確定了最短距離的頂點集 80 * @return 81 */ 82 private static int minIndex(int[] d, Set<Integer> t) { 83 int index = -1; 84 int min = Integer.MAX_VALUE; 85 for (int i = 0; i < d.length; i++) { 86 if (!t.contains(i) && d[i] < min) { 87 min = d[i]; 88 index = i; 89 } 90 } 91 return index; 92 } 93 94 static int[][] graph = { 95 { 0, 2, 5, 0, 0, 0, 0 }, 96 { 2, 0, 4, 6, 10, 0, 0 }, 97 { 5, 4, 0, 2, 0, 0, 0 }, 98 { 0, 6, 2, 0, 0, 1, 0 }, 99 { 0, 10, 0, 0, 0, 3, 5 }, 100 { 0, 0, 0, 1, 3, 0, 9 }, 101 { 0, 0, 0, 0, 5, 9, 0 } 102 }; 103 }

結果:

  技術分享圖片

最短路問題之Dijkstra算法