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 相关文章推荐
javascript instanceof,typeof的区别
Mar 24 Javascript
利用location.hash实现跨域iframe自适应
May 04 Javascript
jQuery跨域问题解决方案
Aug 03 Javascript
写给小白的JavaScript引擎指南
Dec 04 Javascript
详解Node.js包的工程目录与NPM包管理器的使用
Feb 16 Javascript
AngularJS实现在ng-Options加上index的解决方法
Nov 03 Javascript
vue+vuecli+webpack中使用mockjs模拟后端数据的示例
Oct 24 Javascript
three.js中文文档学习之通过模块导入
Nov 20 Javascript
vue elementUI table 自定义表头和行合并的实例代码
May 22 Javascript
基于Node.js搭建hexo博客过程详解
Jun 25 Javascript
jQuery实现获取多选框的值示例
Feb 07 jQuery
在react-antd中弹出层form内容传递给父组件的操作
Oct 24 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 GD绘制24小时柱状图
2008/06/28 PHP
php Smarty date_format [格式化时间日期]
2010/03/15 PHP
php遍历数组的4种方法总结
2014/07/05 PHP
PHP实现简单的新闻发布系统实例
2015/07/28 PHP
php实现博客,论坛图片防盗链的方法
2016/10/15 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
2018/02/08 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
JavaScript与C# Windows应用程序交互方法
2007/06/29 Javascript
javascript 面向对象,实现namespace,class,继承,重载
2009/10/29 Javascript
预加载css或javascript的js代码
2010/04/23 Javascript
精通Javascript系列之数值计算
2011/06/07 Javascript
JS实现跟随鼠标闪烁转动色块的方法
2015/02/26 Javascript
javascript中new关键字详解
2015/12/14 Javascript
jQuery动画显示和隐藏效果实例演示(附demo源码下载)
2015/12/31 Javascript
简单封装js的dom查询实例代码
2016/07/08 Javascript
jquery实现图片上传前本地预览
2017/04/28 jQuery
浅谈vuex之mutation和action的基本使用
2017/08/29 Javascript
Bootstrap一款超好用的前端框架
2017/09/25 Javascript
Node.js使用supervisor进行开发中调试的方法
2019/03/26 Javascript
JavaScript实现美化滑块效果
2019/05/17 Javascript
javascript触发模拟鼠标点击事件
2019/06/26 Javascript
vue模块移动组件的实现示例
2020/05/20 Javascript
[16:04]DOTA2海涛带你玩炸弹 9月5日更新内容详解
2014/09/05 DOTA
python文件和目录操作函数小结
2014/07/11 Python
Python实现单词拼写检查
2015/04/25 Python
python 实现将txt文件多行合并为一行并将中间的空格去掉方法
2018/12/20 Python
用canvas画心电图的示例代码
2018/09/10 HTML / CSS
什么是类的返射机制
2016/02/06 面试题
西安启天科技有限公司网络工程师面试题笔试题
2016/06/12 面试题
文艺晚会主持词
2014/03/24 职场文书
我的大学生活演讲稿
2014/04/25 职场文书
单位活动策划方案
2014/08/17 职场文书
2015上半年个人工作总结
2015/07/27 职场文书
积极心理学课程心得体会
2016/01/22 职场文书
《富饶的西沙群岛》教学反思
2016/02/16 职场文书
纯CSS打字动画的实现示例
2022/08/05 HTML / CSS