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下判断Id是否存在的代码
Jan 06 Javascript
JS+DIV实现鼠标划过切换层效果的方法
May 25 Javascript
jQuery实现的Div窗口震动效果实例
Aug 07 Javascript
纯JavaScript代码实现文本比较工具
Feb 17 Javascript
Angularjs之filter过滤器(推荐)
Nov 27 Javascript
javascript容错处理代码(屏蔽js错误)
Jan 20 Javascript
JavaScript数据结构之链表的实现
Mar 19 Javascript
Vue声明式渲染详解
May 17 Javascript
详解基于node的前端项目编译时内存溢出问题
Aug 01 Javascript
React Native仿美团下拉菜单的实例代码
Aug 08 Javascript
基于js实现抽红包并分配代码实例
Sep 19 Javascript
node后端服务保活的实现
Nov 10 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
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
php下安装配置fckeditor编辑器的方法
2011/03/02 PHP
供参考的 php 学习提高路线分享
2011/10/23 PHP
php抽象类使用要点与注意事项分析
2015/02/09 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
发一个自己用JS写的实用看图工具实现代码
2008/07/26 Javascript
如何让页面在打开时自动刷新一次让图片全部显示
2012/12/17 Javascript
原生javascript实现图片按钮切换
2015/01/12 Javascript
浅谈JSON中stringify 函数、toJosn函数和parse函数
2015/01/26 Javascript
js判断节假日实例代码
2017/12/27 Javascript
微信小程序实现自定义picker选择器弹窗内容
2020/05/26 Javascript
详解如何搭建mpvue框架搭配vant组件库的小程序项目
2019/05/16 Javascript
js实现随机8位验证码
2020/07/24 Javascript
通过js给网页加上水印背景实例
2019/06/17 Javascript
[06:07]辉夜杯现场观众互动 “比谁远送显示器”
2015/12/26 DOTA
在Python中marshal对象序列化的相关知识
2015/07/01 Python
Python中max函数用法实例分析
2015/07/17 Python
Python 3.x读写csv文件中数字的方法示例
2017/08/29 Python
Python实现PS图像明亮度调整效果示例
2018/01/23 Python
pandas.dataframe按行索引表达式选取方法
2018/10/30 Python
python实现列表中最大最小值输出的示例
2019/07/09 Python
解决Django layui {{}}冲突的问题
2019/08/29 Python
python实现感知机模型的示例
2020/09/30 Python
基于HTML5+Webkit实现树叶飘落动画
2017/12/28 HTML / CSS
销售员自我评价怎么写
2013/09/19 职场文书
大学生创业计划书的用途
2014/01/08 职场文书
租赁意向书范本
2014/04/01 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
工程承包协议书
2014/10/20 职场文书
2015年党支部公开承诺书
2015/01/22 职场文书
2015年酒店工作总结
2015/04/28 职场文书
六年级上册《闻官军收河南河北》的教学设计
2019/11/15 职场文书
php访问对象中的成员的实例方法
2021/11/17 PHP
船舶调度指挥系统——助力智慧海事
2022/02/18 无线电
「女孩的钓鱼慢活」全新版权绘公布
2022/03/21 日漫