实现代码如下:
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;
}
}
}