實現代碼如下:
var n = 3; var dis = [0]; var mark = []; var arr = []; var inf = 9999; var i, j, k; //init for (i = 0; i < n; i++) { mark.push(1); arr[i] = []; for (j = 0; j < n; j++) { arr[i][j] = inf;//i->j,init 9999 } } arr[0][1] = 3; arr[1][2] = -2; arr[0][2] = 6; //init dis dis[0] = 0; for (j = 1; j < arr.length; j++) { dis[j] = arr[0][j]; } mark[0] = 0; for (i = 0; i < arr.length - 1; i++) {//去除源點自身,從剩下的點中選出離源點距離最小的點,因此只需進行n-1輪尋找 var min = [0, 0, inf];//src,dis,weight for (j = 0; j < arr.length; j++) { //找出最小值 if (mark[j]) { if (arr[i][j] < min[2]) { min = [i, j, arr[i][j]]; } } } mark[min[1]] = 0;//將dis最小的點min[1]標記為選中 for (k = 0; k < arr.length; k++) {//比較 min[1]->k + 源點到min[1]的距離dis[[min[1]]],是否比dis[k]的距離要小 if (arr[min[1]][k] + dis[min[1]] < dis[k]) { dis[k] = arr[min[1]][k] + dis[min[1]];//鬆弛 } } } console.log(dis);
迪傑斯特拉演算法是求單源最短路徑,思路是用一個dis數組儲存源點到各點的距離(源點到自身的距離記為0),然後每次取距離最小的點,對這個點的所有出邊進行鬆弛。
所謂鬆弛(relaxation),比如1->3=10,1->2->3=5,那麼1->3實際上可縮短為5,這就叫做對邊1->3進行了一輪鬆弛操作。
最近在看《啊哈。演算法》,書上說迪傑斯特拉演算法不能有負權邊,我用js寫的這個,試了一下負權邊好像是可以的,只是不能有負權迴路,然後看了書上的Bellman-ford演算法,我覺得除了加上了負權迴路的判斷好像和迪傑斯特拉演算法沒什麼區別。。。嗯,應該是我沒看懂= =
我用js實現了負權迴路的判斷,代碼如下:
var n = 3; var dis = [0]; var mark = []; var arr = []; var inf = 9999; var i, j, k; //init for (i = 0; i < n; i++) { mark.push(1); arr[i] = []; for (j = 0; j < n; j++) { arr[i][j] = inf;//i->j,init 9999 } } arr[0][1] = 3; arr[1][2] = 2; arr[0][2] = 6; arr[2][0] = -1; //init dis dis[0] = 0; for (j = 1; j < arr.length; j++) { dis[j] = arr[0][j]; } mark[0] = 0; for (i = 0; i < arr.length - 1; i++) {//去除源點自身,從剩下的點中選出離源點距離最小的點,因此只需進行n-1輪尋找 var min = [0, 0, inf];//src,dis,weight for (j = 0; j < arr.length; j++) { //找出最小值 if (mark[j]) { if (arr[i][j] < min[2]) { min = [i, j, arr[i][j]]; } } } mark[min[1]] = 0;//將dis最小的點min[1]標記為選中 for (k = 0; k < arr.length; k++) {//比較 min[1]->k + 源點到min[1]的距離dis[[min[1]]],是否比dis[k]的距離要小 if (arr[min[1]][k] + dis[min[1]] < dis[k]) { dis[k] = arr[min[1]][k] + dis[min[1]];//鬆弛 arr[0][k] = dis[k];//同時修改數組值,用於判斷是否有負權迴路 } } } console.log(dis); /*檢測是否有負權迴路*/ for (i = 0; i < arr.length; i++) { for (j = 0; j < arr.length; j++) { if (arr[0][j] > dis[i] + arr[i][j]) { console.log("有負權迴路", "0->", i, "->", j); break; } } }