Dijkstra演算法-(迪傑斯特拉)演算法的迭代實現與優先佇列實現 圖解演算法過程
阿新 • • 發佈:2019-01-31
Dijkstra演算法-(迪傑斯特拉)演算法之迭代實現 Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列實現
該演算法的核心原理,很簡單,如下圖所示:
先說說Dijkstra演算法-(迪傑斯特拉)演算法之迭代實現,如下圖為詳細步驟,
程式碼如下,兩種實現方法都有,用優先佇列實現的演算法更優秀。
package com.collonn.algorithm; import java.util.PriorityQueue; /** * 帶權有向圖的單源最短路徑<br/> * Dijkstra演算法-(迪傑斯特拉)演算法<br/> */ public class GrfDijkstra { // 為了矩陣的輸出更直觀好看一些,本例中約定,路徑權值取值範圍為:[1,10],權值為999表示無連通 // 並假設所有權值的和小於999 private final int MAX = 999; // 頂點總數 private int total; // 頂點資訊 private String[] nodes; // 頂點矩陣 private int[][] matirx; // 源點到各頂點的距離 private int[] dis; // 頂點是否已標記 private int[] mark; public GrfDijkstra(int total, String[] nodes) { this.total = total; this.nodes = nodes; this.matirx = new int[total][total]; this.dis = new int[total]; this.mark = new int[total]; } private void printMatrix() { System.out.println("--------- weighted directed matrix ---------"); System.out.println("---0---1---2---3---4---5---6---7---8---"); System.out.println("---A---B---C---D---E---F---G---H---I---"); for (int i = 0; i < this.total; i++) { System.out.print("-" + this.nodes[i] + "|"); for (int j = 0; j < this.total; j++) { System.out.print(String.format("%03d", this.matirx[i][j]) + "-"); } System.out.print("\n"); } System.out.println("--------- weighted directed matrix ---------"); } /** * Dijkstra演算法-(迪傑斯特拉)演算法之迭代實現 * * @param s * 源點(起點) */ public void dijkstra(int s) { // 初始化 for (int i = 0; i < this.total; i++) { // 初始化都未標記 this.mark[i] = 0; // 給源點的直接鄰接點加上初始權值 this.dis[i] = this.matirx[s][i]; } // 將源點s加入已標記 this.mark[s] = 1; // 頂點到自身的距離為0 this.dis[s] = 0; // 臨時最短距離 int min = -1; // 臨時最短距離的頂點 int k = -1; this.printDis(0, "屌", "初始化"); // 除去源點s到自身的距離為0外,還要不斷的進行距離修正(源點s到其它頂點(共total-1個)的最短距離) for (int i = 1; i < this.total; i++) { // 從當前最新的,源點到其它各頂點的距離資訊陣列dis[]中,找到一個沒有標記過的, // 並且距離(從源點到該某頂點)最短的頂點 min = MAX; for (int j = 0; j < this.total; j++) { if (this.mark[j] == 0 && this.dis[j] < min) { min = this.dis[j]; k = j; } } // 標記該頂點 this.mark[k] = 1; /** * 距離校正<br/> */ for (int j = 0; j < this.total; j++) { if (this.mark[j] == 0 && (this.matirx[k][j] + this.dis[k]) < this.dis[j]) { this.dis[j] = this.matirx[k][j] + this.dis[k]; } } this.printDis(i, this.nodes[k], "進行中"); } } /** * Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列實現 */ public void dijkstraPQ() { // Item是PriorityQueue中元素,實現了Comparable介面,優先佇列用此介面進行排序 class Item implements Comparable<Item> { // 節點在陣列的下標 public int idx; // 到改節點的臨時最小權值和 public int weight; public Item(int idx, int weight) { this.idx = idx; this.weight = weight; } @Override public int compareTo(Item item) { if (this.weight == item.weight) { return 0; } else if (this.weight < item.weight) { return -1; } else { return 1; } } } // 值較小的元素總是在優先佇列的頭部,值較大的元素總是在優先佇列的尾部 PriorityQueue<Item> pq = new PriorityQueue<Item>(); // 將源點(即起點)加入到優先佇列 pq.offer(new Item(0, 0)); Item itm = null; while (!pq.isEmpty()) { itm = pq.poll(); // 圖中某節點下標 int idx = itm.idx; // 到某節點的臨時最小權值和 int weight = itm.weight; // 如果該元素還未標記,則更新最小權值各 if (this.mark[idx] == 0) { this.dis[idx] = weight; } // 找出該元素(假設A)的所有未標記的鄰接點(假設B) // 則,源點到B的距離可表示為:(源點到A的距離) + (A到B的距離) // 將源點到B的距離加入到優先佇列中 for (int i = 0; i < this.total; i++) { if (this.mark[i] == 0) { pq.offer(new Item(i, this.dis[idx] + this.matirx[idx][i])); } } } } private void printDis(int i, String node, String pre) { System.out.print("\n" + pre + "," + node + "," + i + "--->"); for (int t = 0; t < this.dis.length; t++) { System.out.print(t + ","); } System.out.print("\n" + pre + i + "--->"); for (int t : this.dis) { System.out.print(t + ","); } System.out.print("\n"); } // 初始化圖資料 // 0---1---2---3---4---5---6---7---8--- // A---B---C---D---E---F---G---H---I--- private void initGrf() { // 初始化矩陣為最大值(各節點都不連通) for (int i = 0; i < this.total; i++) { for (int j = 0; j < this.total; j++) { if (i == j) { this.matirx[i][j] = 0; } else { this.matirx[i][j] = MAX; } } } // 手動設定有向路徑 // A->B, A->E, A->D this.matirx[0][1] = 2; this.matirx[0][4] = 3; this.matirx[0][3] = 1; // B->C this.matirx[1][2] = 2; // C->F this.matirx[2][5] = 1; // D->E, D->G this.matirx[3][4] = 5; this.matirx[3][6] = 2; // E->F, E->H this.matirx[4][5] = 6; this.matirx[4][7] = 1; // F->I this.matirx[5][8] = 3; // G->H this.matirx[6][7] = 4; // H->F, H->I this.matirx[7][5] = 1; this.matirx[7][8] = 2; } public static void main(String[] args) { String[] nodes = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" }; GrfDijkstra grf = new GrfDijkstra(nodes.length, nodes); grf.initGrf(); grf.printMatrix(); System.out.println(); System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之迭代開始 ------"); grf.dijkstra(0); grf.printDis(0, "屌", "最終值"); System.out.print("\n"); System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之迭代結束 ------"); System.out.println(); System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列開始 ------"); grf.dijkstraPQ(); grf.printDis(0, "屌", "最終值"); System.out.print("\n"); System.out.println("------ Dijkstra演算法-(迪傑斯特拉)演算法之優先佇列結束 ------"); } }
原創博文,轉載請註明出處。
右鍵,檢視圖片,看大圖。