JavaScript实现Dijkstra单源最短路径算法详解
本文详细解析Dijkstra算法在JavaScript中的实现原理,通过邻接矩阵表示图结构,演示如何初始化距离数组并迭代更新最短路径。文章结合具体示例图解求解步骤,并提供完整代码实现,适用于单源最短路径计算场景。
Dijkstra算法思路解析
一、Dijkstra算法的思路
Dijkstra算法主要用于解决单源点最短路径问题。
其核心逻辑如下:
1. 将图中的顶点划分为两个集合:已确定最短路径的顶点集合Q,以及尚未确定(或无法到达)的顶点集合R。
2. 创建一个距离数组distance,用于记录源点到各个顶点的当前最短距离。数组下标对应顶点编号,元素值为距离值。源点(start)到自身的初始距离设为0,而源点无法直接到达的顶点距离初始化为一个极大值(如Infinity)。
3. 遍历distance数组,选取值为非Infinity的顶点V作为中转点。若通过V到达顶点W的距离(即distance[V] + matrix[V][W])小于当前记录的distance[W],则更新distance[W]为distance[V] + matrix[V][W]。
4. 重复上述遍历与更新过程,直到集合R为空,即所有可达顶点的最短路径均已确定。
具体求解示例
二、具体例子
此处沿用前文《最小生成树算法——Prim算法和Kruskal算法的JS实现》中的图结构作为示例。

该图的邻接矩阵表示如下:

求解步骤
第一步:假设源点为V0,此时集合Q中仅包含{V0},集合R包含{V1, V2, V3, V4}。
第二步:初始化distance数组,初始状态如下所示。

第三步:选取distance中值为非Infinity的顶点作为中转点,本例中为V0。根据规则:若distance[V] + matrix[V][W] < distance[W],则更新distance[W] = distance[V] + matrix[V][W]。更新后,distance数组发生变化,同时集合Q扩展为{V0, V1, V2, V4},集合R剩余{V3}。

第四步:由于集合R中仍有顶点,继续执行第三步。此时以V1为中转点,但发现通过V1到达其他未访问顶点的距离并未小于现有distance值,因此distance数组和两个集合均未发生更新。

第五步:由于集合R中尚存1个顶点,故重复第三步操作,此时以V2作为中转跳点。经检测,V0至V3的距离得以更新,因2 + 3 < 9,故distance值更新,集合亦随之更新。

后续步骤同理,直至遍历完distance数组,输出最终结果。

JavaScript代码实现与复杂度分析
三、代码实现
当前代码实现未处理权值为负数的情况,尚未经过负权值验证。目前版本仅针对权值为正数的图进行实现,后续计划进一步完善以支持负权值场景。
此外,该算法针对单源点求最短路径。若需计算全图各顶点间的最短路径,只需遍历所有顶点并依次调用Dijkstra算法。考虑到Dijkstra算法本身的时间复杂度,全图计算的总时间复杂度将为O(n^3)。
/**
* Dijkstra算法:单源最短路径
* 思路:
* 1. 将顶点分为两部分:已经知道当前最短路径的顶点集合Q和无法到达顶点集合R。
* 2. 定义一个距离数组(distance)记录源点到各顶点的距离,下标表示顶点,元素值为距离。源点(start)到自身的距离为0,源点无法到达的顶点的距离就是一个大数(比如Infinity)。
* 3. 以距离数组中值为非Infinity的顶点V为中转跳点,假设V跳转至顶点W的距离加上顶点V至源点的距离还小于顶点W至源点的距离,那么就可以更新顶点W至源点的距离。即下面distance[V] + matrix[V][W] < distance[W],那么distance[W] = distance[V] + matrix[V][W]。
* 4. 重复上一步骤,即遍历距离数组,同时无法到达顶点集合R为空。
*
* @param matrix 邻接矩阵,表示图
* @param start 起点
*
*
*
* 如果求全图各顶点作为源点的全部最短路径,则遍历使用Dijkstra算法即可,不过时间复杂度就变成O(n^3)了
* */
function Dijkstra(matrix, start = 0) {
const rows = matrix.length,//rows和cols一样,其实就是顶点个数
cols = matrix[0].length;
if(rows !== cols || start >= rows) return new Error("邻接矩阵错误或者源点错误");
//初始化distance
const distance = new Array(rows).fill(Infinity);
distance[start] = 0;
for(let i = 0; i < rows; i++) {
//达到不了的顶点不能作为中转跳点
if(distance[i] < Infinity) {
for(let j = 0; j < cols; j++) {
//比如通过比较distance[i] + matrix[i][j]和distance[j]的大小来决定是否更新distance[j]。
if(matrix[i][j] + distance[i] < distance[j]) {
distance[j] = matrix[i][j] + distance[i];
}
}
console.log(distance);
}
}
return distance;
}
/**
* 邻接矩阵
* 值为顶点与顶点之间边的权值,0表示无自环,一个大数表示无边(比如10000)
* */
const MAX_INTEGER = Infinity;//没有边或者有向图中无法到达
const MIN_INTEGER = 0;//没有自环
const matrix= [
[MIN_INTEGER, 9, 2, MAX_INTEGER, 6],
[9, MIN_INTEGER, 3, MAX_INTEGER, MAX_INTEGER],
[2, 3, MIN_INTEGER, 5, MAX_INTEGER],
[MAX_INTEGER, MAX_INTEGER, 5, MIN_INTEGER, 1],
[6, MAX_INTEGER, MAX_INTEGER, 1, MIN_INTEGER]
];
console.log(Dijkstra(matrix, 0));//[ 0, 5, 2, 7, 6 ]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
