JavaScript实现Dijkstra单源最短路径算法详解

作者:异步漫步时间:2026-10-22 20:27:56浏览:169

本文详细解析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实现》中的图结构作为示例。

Dijkstra算法思路解析

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

Dijkstra算法思路解析

求解步骤

第一步:假设源点为V0,此时集合Q中仅包含{V0},集合R包含{V1, V2, V3, V4}。

第二步:初始化distance数组,初始状态如下所示。

Dijkstra算法思路解析

第三步:选取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}。

Dijkstra算法思路解析

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

Dijkstra算法思路解析

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

Dijkstra算法思路解析

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

Dijkstra算法思路解析

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 ]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章