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;javascript代码
Mar 27 Javascript
js查找父节点的简单方法
Jun 28 Javascript
xml 封装与解析(javascript和C#中)
Jul 26 Javascript
Jquery 获取checkbox的checked问题
Nov 16 Javascript
Javascript selection的兼容性写法介绍
Dec 20 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
jQuery插件dataTables添加序号列的方法
Jul 06 Javascript
web 屏蔽BackSpace键实例代码
Dec 24 Javascript
一份超级详细的Vue-cli3.0使用教程【推荐】
Nov 15 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
Dec 13 Javascript
angular 用Observable实现异步调用的方法
Dec 27 Javascript
一篇文章带你从零快速上手Rollup
Sep 07 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
Laravel 5框架学习之表单
2015/04/08 PHP
用PHP写的一个冒泡排序法的函数简单实例
2016/05/26 PHP
PHP+MySQL存储数据常见中文乱码问题小结
2016/06/13 PHP
PHP上传Excel文件导入数据到MySQL数据库示例
2016/10/25 PHP
阿里云的WindowsServer2016上部署php+apache
2018/07/17 PHP
CSS中一些@规则的用法小结
2021/03/09 HTML / CSS
ExtJs GridPanel简单的增删改实现代码
2010/08/26 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
2014/01/14 Javascript
jQuery模拟新浪微博首页滚动效果的方法
2015/03/11 Javascript
JavaScript编程的单例设计模讲解
2015/11/10 Javascript
浅析JavaScript中浏览器的兼容问题
2016/04/19 Javascript
AngularJS控制器继承自另一控制器
2016/05/09 Javascript
用JavaScript获取页面文档内容的实现代码
2016/06/10 Javascript
浅谈JavaScript 数据属性和访问器属性
2016/09/01 Javascript
jQuery弹出遮罩层效果完整示例
2016/09/13 Javascript
深入理解JS实现快速排序和去重
2016/10/17 Javascript
JS脚本实现网页自动秒杀点击
2018/01/11 Javascript
微信小程序左滑删除功能开发案例详解
2018/11/12 Javascript
[10:24]郎朗助力完美“圣”典,天籁交织奏响序曲
2016/12/18 DOTA
pandas中去除指定字符的实例
2018/05/18 Python
基于Python List的赋值方法
2018/06/23 Python
python数据结构学习之实现线性表的顺序
2018/09/28 Python
python获取指定日期范围内的每一天,每个月,每季度的方法
2019/08/08 Python
python字符串格式化方式解析
2019/10/19 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
2020/11/28 Python
css3高级选择器使用方法
2013/12/02 HTML / CSS
女装和独特珠宝:Sundance Catalog
2018/09/19 全球购物
STP的判定过程
2012/10/01 面试题
linux面试题参考答案(4)
2013/01/28 面试题
商务英语专业应届毕业生求职信
2013/10/28 职场文书
护理专业自荐信
2013/12/03 职场文书
观看《周恩来的四个昼夜》思想汇报
2014/09/12 职场文书
教师纪念9.18事件演讲稿范文
2014/09/14 职场文书
2015年班组建设工作总结
2015/05/13 职场文书
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis