1. 程式人生 > >迪傑斯特拉演算法處理無向圖中最短路徑的(dijkstra)Java實現(指定兩點,求最短距離及路徑)

迪傑斯特拉演算法處理無向圖中最短路徑的(dijkstra)Java實現(指定兩點,求最短距離及路徑)

其實不是原創哈,我寫不出來。

      如何求圖中V0到V5的最短路徑呢?
        java實現的方式如下: 
       第一步,根據圖來建立權值矩陣:
       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不相鄰,所以權值無限大。
第二步:對V0標號;V0到其它點的路徑得到 distance: {0,1,4,-1,-1,-1}; 找到V0到各點中權值最小的那個點(標號的點除外,-1代表無限大),故得到1即對應的下標1,得到V1;對V1標號,然後更改V0通過V1到其它點的路徑得到 distance: { 0, 1, 3, 8, 6, -1}; 
第三步:找到distance中權值最小的那個點,(標號的點除外)得到V2,對V2標號,然後更改V0通過V1->V2到其它點的路徑得到 distance: { 0, 1, 3, 8, 4, -1}; 
第四步:找到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了。結束!
原始碼如下:

package reverse;


//這個演算法用來解決無向圖中任意兩點的最短路徑,同時輸出路徑(起點到所有點的)
public class Success_SQ {

public static String dijkstra(int[][] W1, int start, int end) {

System.out.println("起點:" + start + "終點:" + end);
boolean[] isLabel = new boolean[W1[0].length];// 是否標號
int[] indexs = new int[W1[0].length];// 所有標號的點的下標集合,以標號的先後順序進行儲存,實際上是一個以陣列表示的棧
int i_count = -1;// 棧的頂點
int[] distance = W1[start].clone();// v0到各點的最短距離的初始值
int index = start;// 從初始點開始
int presentShortest = 0;// 當前臨時最短距離


indexs[++i_count] = index;// 把已經標號的下標存入下標集中
isLabel[index] = true;


while (i_count < W1[0].length) {
// 第一步:得到與原點最近的某個點
int min = Integer.MAX_VALUE;
for (int i = 0; i < distance.length; i++) {
if (!isLabel[i] && distance[i] != -1 && i != index) {
// 如果到這個點有邊,並且沒有被標號
if (distance[i] < min) {
min = distance[i];
index = i;// 把下標改為當前下標
}
}
}
i_count = i_count + 1;
if(i_count == W1[0].length){
break;
}
isLabel[index] = true;// 對點進行標號
indexs[i_count] = index;// 把已經標號的下標存入下標集中


if (W1[indexs[i_count - 1]][index] == -1
|| presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) {
// 如果兩個點沒有直接相連,或者兩個點的路徑大於最短路徑
presentShortest = distance[index];
} else {
presentShortest += W1[indexs[i_count - 1]][index];
}

// 第二步:加入vi後,重新計算distance中的距離
for (int i = 0; i < distance.length; i++) {


// 如果vi到那個點有邊,則v0到後面點的距離加
if (distance[i] == -1 && W1[index][i] != -1) {// 如果以前不可達,則現在可達了
distance[i] = presentShortest + W1[index][i];
} else if (W1[index][i] != -1 && presentShortest + W1[index][i] < distance[i]) {
// 如果以前可達,但現在的路徑比以前更短,則更換成更短的路徑
distance[i] = presentShortest + W1[index][i];
}


}


}
getRoute(W1,indexs,end);
return "最短距離是:" + (distance[end] - distance[start]);
}


public static void main(String[] args) {
// 建立一個權值矩陣
int[][] W1 = { // 測試資料1
{ 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 } };
// System.out.println("f" + W1[0][4]);


int[][] W = { // 測試資料2
{ 0, 1, 3, 4 },
{ 1, 0, 2, -1 },
{ 3, 2, 0, 5 }, 
{ 4, -1, 5, 0 } };




System.out.println(dijkstra(W1, 5, 0)); // (int[][] W1, int start, int end)


}


// indexs:1,0,2,4,3,5 放頂點的順序
// end:最後要的頂點名稱:5
// routeLength:長度:8
/**
* seven
* 輸出路徑(起點到所有點的)
*/
public static String getRoute(int[][] WW, int[] indexs, int end) {
String[] routeArray = new String[indexs.length];
for (int i = 0; i < routeArray.length; i++) {
routeArray[i] = "";
}

//自己的路線
routeArray[indexs[0]] = indexs[0] + "";
for (int i = 1; i < indexs.length; i++) {
//看該點與前面所有點的連線線中的最短路徑,然後得到該最短路徑到底是連線了哪個點,進而此點的route就是找出那點的route+此點
int[] thePointDis = WW[indexs[i]];  
int prePoint = 0;

int tmp = 9999;
for(int j=0;j<thePointDis.length;j++){

boolean chooseFlag = false;
//邊的距離最短,而且,所連的點在前面的點當中
for(int m=0;m<i;m++){
if(j == indexs[m]){
chooseFlag = true;
}
}
if(chooseFlag == false){
continue;
}
if(thePointDis[j] <tmp && thePointDis[j] >0){
prePoint = j;
tmp = thePointDis[j];
}
}
routeArray[indexs[i]] = routeArray[prePoint] + indexs[i];
}
for (int i = 0; i < routeArray.length; i++) {
System.out.println(routeArray[i]);
}
return "";
}
}