JS实现单源最短路径,Dijkstra算法
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
算法开始从起始点出发,每次寻找与起始点距离最近且未访问过的顶点,以该顶点作为中间节点,更新从起始点到其他顶点的距离,直到全部顶点都作为了中间节点,并且完成了路径更新算法结束。
引入具体案例分析:
1.先来个有向图(有方向)
已知图像如下,以顶点A为起始点,求到其余顶点之间的最短路径。
//首先,先定义表示上图的邻接矩阵
let graph = [
[0, 2, 4, 0, 0, 0],
[0, 0, 2, 4, 2, 0],
[0, 0, 0, 0, 3, 0],
[0, 0, 0, 0, 0, 2],
[0, 0, 0, 3, 0, 2],
[0, 0, 0, 0, 0, 0]
];
//然后,把所有的距离初始化为无限大
//let inf = Number.POSITIVE_INFINITY;
let inf = Infinity;
//从尚未处理的顶点中选出距离最近的顶点
function minDistance(dist, visit) {
let min = inf
let minIndex = -1
for(let i =0; i < dist.length; i++) {
if(!visit[i] && dist[i] < min) {
minIndex = i
min = dist[i]
}
}
return minIndex
};
//算法函数
function dijkstra(start) {
//设置变量dist存储从起始节点到其他节点的最短路径距离
let dist = []
//将存储访问过的顶点数组visit[]初始化为false
let visit = []
let length = graph.length
for (let i = 0; i < length; i++) {
dist[i] = inf
visit[i] = false
}
//把源顶点到自己的距离设为0
dist[start] = 0
//找出到其余顶点的最短距离(只需要算length -1次,最后一个点前面的已经被标记为已访问)
for (let j = 0; j < length - 1; j++) {
//从尚未处理的顶点中选出距离最近的顶点
let u = minDistance(dist, visit)
//把选出的顶点标为visited,以避免重复计算
visit[u] = true
for (let v = 0; v < length; v++) {
if (
//已经被处理过的点,已经得到了最短的距离,无需再次计算
!visit[v] &&
//这种情况出现于dijkstra(1)这种情况,源点(start)存在无法到达某一个点A,当然这里不会走到这一步,因为只循环了length-1次,如果存在两个无法到达的点,那么再处理最后一次时,便会出现这种情况
dist[u] != inf &&
//当前处理的u点和v点不相邻
graph[u][v] != 0 &&
//如果找到更短的路径,则更新最短路径的值
dist[u] + graph[u][v] < dist[v]
) {
dist[v] = dist[u] + graph[u][v]
}
}
}
//处理完所有顶点后,返回源顶点(start)到图中其他顶点最短路径的结果
return dist
};
//测试
const res = dijkstra(0)
console.log(`A点到各个点最短路径:${res}`); /* 结果: A点到各个点最短路径:0,2,4,6,4,6*/
// [0, 2, 4, 6, 4, 6]
// 求B点到其他个点的最短距离
// const res = dijkstra(1);
// console.log(`B点到各个点最短路径:${res}`); /* 结果: */
// Infinity表示点B与点A不相邻,从上图可知A与B相邻,而B与A不相邻
// [Infinity, 0, 2, 4, 2, 4]
2.再来个无向图
已知图像如下,以北京为起始点,求到其他城市的最短距离。
//同样的代码,不过邻接矩阵换成以下矩阵
let graph = [
[0, 100, 1200, Infinity, Infinity, Infinity],
[100, 0, 900, 300 , Infinity , Infinity],
[1200, 900, 0, 400, 500 , Infinity, Infinity],
[Infinity, 300, 400, 0, 1300, 1400],
[Infinity, Infinity, 500, 1300, 1500],
[Infinity, Infinity, Infinity, 1400, 1500]
];
//测试
const res = dijkstra(0)
console.log(`北京到各个城市的最短路径:${res}`); /* 结果:北京到各个城市的最短路径:0,100,800,400,1300,1800 */
//const res = dijkstra(1);
//console.log(`天津到各个城市的最短路径:${res}`); /* 结果:天津到各个城市的最短路径:100,0,700,300,1200,1700 */
ps:贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
标签:无