算法思想
以起始點為中心向外層層擴展,直到擴展到終點為止。
算法主要步驟
1.構建二維數組weight存儲無向圖,weight[i][j]表示節點i到節點j的權值,即節點i到節點j的距離(下文以dij表示)。
2.構建數組shortpath,存儲起始節點(0)到各節點最短距離,即d0j(j為所有節點),初始化shortpath[0] = 0,其他值為無窮大。
3.構建數組visited,標記各節點是否已被擴展(假設0為為擴展,1為已擴展),初始化visited[0] = 1,其他值為零。
4.迭代算法,遍歷二維數組weight,選擇離起始節點距離最短的未標記結點k,將d0k記錄至shortpath,並將k標記為已擴展,
通過k更新起始節點到其他各節點的距離,若d0j > d0k + dkj ,則d0j = d0k + dkj。
代碼實現
public static int[] Dijsktra(int [][] weight,int start){ int length = weight.length;//獲取頂點個數 int[] shortPath = new int[length];//最短路徑數組 shortPath[0] = 0;// String[] path = new String[length];//記錄起始點到各定點的最短路徑 for(int i = 0 ; i < length ; i++){ path[i] = start + "->" + i; } int[] visited = new int[length];//記錄當前頂點的最短路徑是否已經求出,1表示已求出 for(int i = 0 ; i < length ; i++){ visited[i] = 0; } visited[0] = 1;//起始點的最短路徑已經求出 for(int m = 1 ; m < length ; m ++){ int k = -1; int dmin = Integer.MAX_VALUE; //選擇一個離起始點最近的未標記頂點,且到起始點的最短路徑為dmin for(int n = 0 ; n < length ; n++){ if(visited[n] == 0 && weight[start][n] < dmin){ dmin = weight[start][n]; k = n; } } shortPath[k] = dmin; visited[k] = 1; //以k為中間點,更新起始點到其他未標記各點的距離 for(int j = 0 ; j < length ; j++){ if(visited[j] == 0 && weight[k][j] != Integer.MAX_VALUE && weight[start][k] + weight[k][j] < weight[start][j]){ weight[start][j] = weight[start][k] + weight[k][j]; path[j] = path[k] + "->" + j; } } } for(int i = 1 ; i < length ; i ++){ System.out.println("起始點到" + i + "的最短路徑為:" + path[i] + "距離為:" + shortPath[i]); } return shortPath; }
聲明常量
public static final int MAX = Integer.MAX_VALUE;
代碼測試
public static void main(String[] args) { int[][] weigth = {{0,50,70,MAX,MAX}, {50,0,15,30,MAX}, {70,15,0,MAX,40}, {MAX,30,MAX,0,20}, {MAX,MAX,40,20,0}}; Dijsktra(weigth,0); }
運行結果
起始點到1的最短路徑為:0->1距離為:50
起始點到2的最短路徑為:0->1->2距離為:65
起始點到3的最短路徑為:0->1->3距離為:80
起始點到4的最短路徑為:0->1->3->4距離為:100