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 相关文章推荐
尽可能写&quot;友好&quot;的&quot;Javascript&quot;代码
Jan 09 Javascript
JQuery复制DOM节点的方法
Jun 11 Javascript
jQuery Ajax请求后台数据并在前台接收
Dec 10 Javascript
Centos6.8下Node.js安装教程
May 12 Javascript
vue bootstrap小例子一枚
Jun 09 Javascript
Vue下滚动到页面底部无限加载数据的示例代码
Apr 22 Javascript
详解CommonJS和ES6模块循环加载处理的区别
Dec 26 Javascript
vue路由--网站导航功能详解
Mar 29 Javascript
微信小程序实现录音时的麦克风动画效果实例
May 18 Javascript
vue项目中使用bpmn为节点添加颜色的方法
Apr 30 Javascript
VUE : vue-cli中去掉路由中的井号#操作
Sep 04 Javascript
Vue实现一种简单的无限循环滚动动画的示例
Jan 10 Vue.js
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计算百度地图两个GPS坐标之间距离的方法
2015/01/09 PHP
PHP中Http协议post请求参数
2015/11/02 PHP
laravel config文件配置全局变量的例子
2019/10/13 PHP
cssQuery()的下载与使用方法
2007/01/12 Javascript
javascript之水平横向滚动歌词同步的应用
2007/05/07 Javascript
javascript Prototype 对象扩展
2009/05/15 Javascript
Javascript 构造函数,公有,私有特权和静态成员定义方法
2009/11/30 Javascript
jQuery实现的Email中的收件人效果(按del键删除)
2011/03/20 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
js实现简单登录功能的实例代码
2013/11/09 Javascript
鼠标经过tr时,改变tr当前背景颜色
2014/01/13 Javascript
jQuery实现自定义右键菜单的树状菜单效果
2015/09/02 Javascript
JavaScript中字符串与Unicode编码互相转换的实现方法
2015/12/18 Javascript
jquery实现页面常用的返回顶部效果
2016/03/04 Javascript
倾力总结40条常见的移动端Web页面问题解决方案
2016/05/24 Javascript
利用js来实现缩略语列表、文献来源链接和快捷键列表
2016/12/16 Javascript
JS实现获取来自百度,Google,soso,sogou关键词的方法
2016/12/21 Javascript
20行js代码实现的贪吃蛇小游戏
2017/06/20 Javascript
微信小程序表单验证功能完整实例
2017/12/01 Javascript
Vue拖拽组件列表实现动态页面配置功能
2019/06/17 Javascript
React+Redux实现简单的待办事项列表ToDoList
2019/09/29 Javascript
vue router返回到指定的路由的场景分析
2020/11/10 Javascript
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
Pyhthon中使用compileall模块编译源文件为pyc文件
2015/04/28 Python
解密Python中的描述符(descriptor)
2015/06/03 Python
对python中数据集划分函数StratifiedShuffleSplit的使用详解
2018/12/11 Python
Python + OpenCV 实现LBP特征提取的示例代码
2019/07/11 Python
TensorFlow加载模型时出错的解决方式
2020/02/06 Python
详解如何在登录过期后跳出Ifram框架
2020/09/10 HTML / CSS
公司活动总结范文
2014/07/01 职场文书
大学毕业生个人自荐书
2014/07/02 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
工作汇报开头与结尾怎么写
2014/11/08 职场文书
会计试用期工作总结2015
2015/05/28 职场文书
公司车队管理制度
2015/08/04 职场文书
导游词之日本富士山
2020/01/06 职场文书