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 相关文章推荐
jQuery CSS()方法改变现有的CSS样式表
Sep 09 Javascript
js使用cookie记录用户名的方法
Nov 26 Javascript
JavaScript中数组slice和splice的对比小结
Sep 22 Javascript
Bootstrap实现的标签页内容切换显示效果示例
May 25 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
Jul 19 Javascript
ES6中javascript实现函数绑定及类的事件绑定功能详解
Nov 08 Javascript
jquery实现购物车基本功能
Oct 25 jQuery
Jquery异步上传文件代码实例
Nov 13 jQuery
jQuery实现简单日历效果
Jul 05 jQuery
vue实现虚拟列表功能的代码
Jul 28 Javascript
小程序实现上下切换位置
Nov 16 Javascript
vue组件的路由高亮问题解决方法
May 11 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
转生史莱姆:萌王第一次撸串开心到飞起,哥布塔撸串却神似界王神
2018/11/30 日漫
PHP URL参数获取方式的四种例子
2014/02/28 PHP
php环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
SSO单点登录的PHP实现方法(Laravel框架)
2016/03/23 PHP
IE与FireFox的兼容性问题分析
2007/04/22 Javascript
JavaScript脚本语言在网页中的简单应用
2007/05/13 Javascript
jQuery实现隔行背景色变色
2014/11/24 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
angularjs学习笔记之三大模块(modal,controller,view)
2015/09/26 Javascript
实例讲解javascript注册事件处理函数
2016/01/09 Javascript
微信小程序 获取设备信息 API实例详解
2016/10/02 Javascript
Angular页面间切换及传值的4种方法
2016/11/04 Javascript
jQuery.Validate表单验证插件的使用示例详解
2017/01/04 Javascript
Three.js基础学习之场景对象
2017/09/27 Javascript
深入理解Vue 的钩子函数
2018/09/05 Javascript
NodeJS http模块用法示例【创建web服务器/客户端】
2019/11/05 NodeJs
从局部变量和全局变量开始全面解析Python中变量的作用域
2016/06/16 Python
Python 获取当前所在目录的方法详解
2017/08/02 Python
Python之reload流程实例代码解析
2018/01/29 Python
Python实现的直接插入排序算法示例
2018/04/29 Python
djano一对一、多对多、分页实例代码
2019/08/16 Python
基于python调用jenkins-cli实现快速发布
2020/08/14 Python
html5的websockets全双工通信详解学习示例
2014/02/26 HTML / CSS
世界上最大的字体市场:MyFonts
2020/01/10 全球购物
荷兰最大的鞋子、服装和运动折扣店:Bristol
2021/01/07 全球购物
C#面试问题
2016/07/29 面试题
销售人员自我评价
2014/02/01 职场文书
求职自荐信的格式
2014/04/07 职场文书
捐助倡议书范文
2014/04/15 职场文书
课前三分钟演讲稿
2014/04/24 职场文书
2014年新生军训方案
2014/05/01 职场文书
学习之星事迹材料
2014/05/17 职场文书
《酸的和甜的》教学反思
2016/02/18 职场文书
如何写好一份优秀的工作总结?
2019/06/21 职场文书
公务员的复习计划书,请收下!
2019/07/15 职场文书
一文了解MySQL二级索引的查询过程
2022/02/24 MySQL