JS使用Dijkstra算法求解最短路径


Posted in Javascript onJanuary 17, 2019

一、Dijkstra算法的思路

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为空。

二、具体例子

偷个懒,直接用上一篇博客《最小生成树算法——Prim算法和Kruskal算法的JS实现》的图为例子。

JS使用Dijkstra算法求解最短路径

它的邻接矩阵如下:

JS使用Dijkstra算法求解最短路径

求解步骤 

第一步:假设源点为V0,那么目前最短路径的顶点集合Q中就只有{V0}和无法到达顶点集合R中有{V1, V2, V3, V4}

第二步:初始化distance数组,就是下面这样

JS使用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}

JS使用Dijkstra算法求解最短路径

第四步:因为集合R中还有1个顶点,所以重复第三步的方法,然后变成以V1为中转跳点,但是以V1为中转顶点都不满足distance[V] + matrix[V][W] < distance[W],所以没更新distance和两个集合

JS使用Dijkstra算法求解最短路径

第五步:因为集合R中还有1个顶点,所以重复第三步的方法,此时变成以V2为中转跳点,然后发现V0到达V3的距离可以更新,因为2 + 3 < 9,所以distance更新,集合也更新。

JS使用Dijkstra算法求解最短路径

之后同理,遍历完distance之后,输出

JS使用Dijkstra算法求解最短路径

三、代码实现

这个代码没有考虑权值为负数的情况,还没验证负数的情况,目前是按照权值为正数实现的,之后考虑完善。 

同时这是针对单源点求最短路径,如果求全图各顶点的最短路径,只需要遍历顶点然后使用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 ]

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

Javascript 相关文章推荐
表单(FORM)的一些实用效果代码
Mar 25 Javascript
简单常用的幻灯片播放实现代码
Sep 25 Javascript
jQuery学习笔记之总体架构
Jun 03 Javascript
关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
Jun 30 Javascript
JS验证 只能输入小数点,数字,负数的实现方法
Oct 07 Javascript
Javascript 普通函数和构造函数的区别
Nov 05 Javascript
JS中关于事件处理函数名后面是否带括号的问题
Nov 16 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 Javascript
vue中element 上传功能的实现思路
Jul 06 Javascript
详解JavaScript中的函数、对象
Apr 01 Javascript
微信小程序 WXML节点信息查询详解
Jul 29 Javascript
javascript 设计模式之组合模式原理与应用详解
Apr 08 Javascript
JavaScript简单实现的仿微博留言功能示例
Jan 17 #Javascript
vue权限管理系统的实现代码
Jan 17 #Javascript
使用nvm和nrm优化node.js工作流的方法
Jan 17 #Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
Jan 17 #Javascript
微信小程序使用wxParse解析html的方法示例
Jan 17 #Javascript
nvm、nrm、npm 安装和使用详解(小结)
Jan 17 #Javascript
JavaScript之实现一个简单的Vue示例
Jan 17 #Javascript
You might like
php调用Google translate_tts api实现代码
2013/08/07 PHP
PHP获取本周第一天和最后一天示例代码
2014/02/24 PHP
一个php短网址的生成代码(仿微博短网址)
2014/05/07 PHP
PHP使用SOAP扩展实现WebService的方法
2016/04/01 PHP
JavaScript继承方式实例
2010/10/29 Javascript
8款非常棒的响应式jQuery 幻灯片插件推荐
2012/02/02 Javascript
解析使用js判断只能输入数字、字母等验证的方法(总结)
2013/05/14 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
jquery实现文本框textarea自适应高度
2016/03/09 Javascript
JS简单设置下拉选择框默认值的方法
2016/08/20 Javascript
使用Angular.js开发的注意事项
2016/10/19 Javascript
Vue动态组件实例解析
2017/08/20 Javascript
vue车牌号校验和银行校验实战
2019/01/23 Javascript
JavaScript实现的弹出遮罩层特效经典示例【基于jQuery】
2019/07/10 jQuery
layui use 定义js外部引用函数的方法
2019/09/26 Javascript
小程序自定义模板实现吸顶功能
2020/01/08 Javascript
原生js实现的金山打字小游戏(实例代码详解)
2020/03/16 Javascript
浅谈vue中使用编辑器vue-quill-editor踩过的坑
2020/08/03 Javascript
详解Java中String JSONObject JSONArray List转换
2020/11/13 Javascript
举例讲解Python中字典的合并值相加与异或对比
2016/06/04 Python
老生常谈Python startswith()函数与endswith函数
2017/09/08 Python
Python基于OpenCV库Adaboost实现人脸识别功能详解
2018/08/25 Python
python3 打印输出字典中特定的某个key的方法示例
2019/07/06 Python
Django1.11配合uni-app发起微信支付的实现
2019/10/12 Python
python如何将两个txt文件内容合并
2019/10/18 Python
matplotlib.pyplot画图并导出保存的实例
2019/12/07 Python
Python3获取cookie常用三种方案
2020/10/05 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
2020/10/15 Python
波兰家居和花园家具专家:4Home
2019/05/26 全球购物
优秀企业获奖感言
2014/02/01 职场文书
《彩色世界》教学反思
2014/04/12 职场文书
军事理论课感想
2015/08/11 职场文书
党校团干班培训心得体会
2016/01/06 职场文书
《丑小鸭》教学反思
2016/02/19 职场文书
java开发双人五子棋游戏
2022/05/06 Java/Android
Spring boot实现上传文件到本地服务器
2022/08/14 Java/Android