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 相关文章推荐
window.parent调用父框架时 ie跟火狐不兼容问题
Jul 30 Javascript
jquery弹出框的用法示例(一)
Aug 26 Javascript
如何在MVC应用程序中使用Jquery
Nov 17 Javascript
javascript十六进制及二进制转化的方法
May 06 Javascript
Jquery Mobile 自定义按钮图标
Nov 18 Javascript
学习JavaScript设计模式之策略模式
Jan 12 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
Nov 29 Javascript
js实现简单的网页换肤效果
Jan 18 Javascript
完美解决input[type=number]无法显示非数字字符的问题
Feb 28 Javascript
webstorm中配置Eslint的两种方式及差异比较详解
Oct 19 Javascript
vue组件化中slot的基本使用方法
May 01 Javascript
JavaScript中的垃圾回收与内存泄漏示例详解
May 02 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和ACCESS写聊天室(二)
2006/10/09 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
2016/03/29 PHP
JavaScript中的对象化编程
2008/01/16 Javascript
Javascript在IE下设置innerHTML时出现未知的运行时错误的解决方法
2011/01/12 Javascript
document.all的一个比较完整的总结及案例
2013/01/31 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
利用css+原生js制作简单的钟表
2020/04/07 Javascript
js中获取 table节点各tr及td的内容简单实例
2016/10/14 Javascript
vue监听scroll的坑的解决方法
2017/09/07 Javascript
vue 系列——vue2-webpack2框架搭建踩坑之路
2017/12/22 Javascript
微信小程序如何获取用户信息
2018/01/26 Javascript
vue 查看dist文件里的结构(多种方式)
2020/01/17 Javascript
Element Collapse 折叠面板的使用方法
2020/07/26 Javascript
解决vue axios跨域 Request Method: OPTIONS问题(预检请求)
2020/08/14 Javascript
python高并发异步服务器核心库forkcore使用方法
2013/11/26 Python
sublime text 3配置使用python操作方法
2017/06/11 Python
Django 如何获取前端发送的头文件详解(推荐)
2017/08/15 Python
python encrypt 实现AES加密的实例详解
2020/02/20 Python
基于Python实现视频的人脸融合功能
2020/06/12 Python
python给视频添加背景音乐并改变音量的具体方法
2020/07/19 Python
Python logging日志库空间不足问题解决
2020/09/14 Python
python pymysql库的常用操作
2020/10/16 Python
综合素质的自我鉴定
2013/10/07 职场文书
学校办公室主任职责
2013/12/27 职场文书
上课迟到检讨书100字
2014/01/11 职场文书
咖啡店自主创业商业计划书
2014/01/22 职场文书
《我的伯父鲁迅先生》教学反思
2014/02/12 职场文书
如何写一封打动人心的求职信
2014/02/17 职场文书
计算机网络及管理学专业求职信
2014/06/05 职场文书
初三语文教学计划
2015/01/22 职场文书
骨干教师个人总结
2015/02/11 职场文书
检讨书范文大全
2015/05/07 职场文书
小学英语教师研修感悟
2015/11/18 职场文书
Python爬虫入门案例之爬取二手房源数据
2021/10/16 Python
十大最强电系宝可梦,阿尔宙斯电系之一,第七被称为雷神
2022/03/18 日漫
JavaScript获取URL参数的方法分享
2022/04/07 Javascript