引言

在Prim算法和Kruskal算法中,我们学习了寻找加权无向图的最小生成树的Prim算法:构造最小生成树的每一步都向生成树中添加一条新的边。

今天要学习类似的方法来计算最短路径——Dijkstra算法。

Dijkstra算法

最短路径树中的边edgeTo[v]的值为树中连接v和它的父节点的边。

最短路径树:包含了顶点s到所有可达的顶点的最短路径

distTo[v]表示从sv的已知最短路径的长度

Dijkstra算法构造最小生成树的每一步都向生成树中添加一条新的边。首先将distTo[s]初始化为0,distTo[]中的
其他元素初始化为正无穷。然后将distTo[]最小的非树顶点加入树中,如此,知道所有的顶点都在树中。

下面通过实例图解分析一下该算法。

对上篇文章图论算法——加权有向图的数据结构中的图例求解最短路径树,过程如下:


初始将0加入优先队列,然后将0增加到最短路径树,同时让它出队。它的邻接点24加入到优先队列中。从队列中找到distTo[]值最小的为distTo[2]=0.26,将对应的边0→2加粗标红。


从队列中删除顶点2,将0→2添加到树中,将7加入优先队列。此时distTo[7] = 0.26 + 0.34 = 0.60。图中黑色粗线表示该条边已经在树中,如0→2。

从队列中删除顶点4,将0→4添加到树中,将5加入优先队列。这里没有将7加入优先队列是因为当前distTo[7] = 0.60 小于从0->4,4->7的路径权重和,意味着边4->7失效。


从队列中删除顶点7,将2→7添加到树中,将3加入优先队列。边7->5失效。


从队列中删除顶点5,将4→5添加到树中,将1加入优先队列。边5->7失效。


从队列中删除顶点3,将7→3添加到树中,将6加入优先队列。


从队列中删除顶点1,将5→1添加到树中,边1->3失效。


从队列中删除顶点6,将3→6添加到树中。

代码

package com.algorithms.graph;import com.algorithms.heap.IndexMinPQ;
import com.algorithms.stack.Stack;/*** 最短路径算法* @author yjw* @date 2019/6/6/006*/
public class DijkstraSP {/*** edgeTo[v]表示从s到v的最短路径上的最后一条边*/private DirectedEdge[] edgeTo;/*** distTo[v]为从s到v的已知最短路径的长度*/private double[] distTo;private IndexMinPQ<Double> pq;public DijkstraSP(EdgeWeightedDigraph g, int s) {edgeTo = new DirectedEdge[g.vertexNum()];distTo = new double[g.vertexNum()];pq = new IndexMinPQ<>(g.vertexNum());//初始化for (int v = 0; v < g.vertexNum(); v++) {distTo[v] = Double.POSITIVE_INFINITY;}//将起点到自己的距离声明为0distTo[s] = 0.0;//入队pq.insert(s, 0.0);while (!pq.isEmpty()) {visit(g, pq.deleteMin());}}private void visit(EdgeWeightedDigraph g, int v) {for (DirectedEdge e : g.adj(v)) {int w = e.to();//distTo[w] > distTo[v] + e.weight()//意思就是,如果经由v点到w点,权重比之前更小(路径更短),则选择经由v点if (Double.compare(distTo[w], distTo[v] + e.weight()) > 0) {//更新从s到w的最短路径长度distTo[w] = distTo[v] + e.weight();//更新边edgeTo[w] = e;//pq中是否含有wif (pq.contains(w)) {//更新索引w对应的值,可能会调整索引堆的结构pq.changeKey(w, distTo[w]);} else {//不存在则插入pqpq.insert(w, distTo[w]);}}}}public double distTo(int v) {return distTo[v];}public boolean hasPathTo(int v) {return distTo[v] < Double.POSITIVE_INFINITY;}public Iterable<DirectedEdge> pathTo(int v) {if (!hasPathTo(v)) {return null;}Stack<DirectedEdge> path = new Stack<>();//从终点开始,不断的取上一条路径,因此利用了栈来打印成起点到终点的正序for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {path.push(e);}return path;}public static void main(String[] args) {EdgeWeightedDigraph g = new EdgeWeightedDigraph(8);g.addEdges(0,2,.26,4,.38);g.addEdge(1,3,.29);g.addEdge(2,7,.34);g.addEdge(3,6,.52);g.addEdges(4,7,.37,5,.35);g.addEdges(5,1,.32,7,.28,4,.35);g.addEdges(6,4,.93,0,.58,2,.40);g.addEdges(7,3,.39,5,.28);DijkstraSP dsp = new DijkstraSP(g,0);for (int v = 0; v < g.vertexNum(); v++) {if (dsp.hasPathTo(v)) {System.out.print("0 to " + v + ": ");for (DirectedEdge e : dsp.pathTo(v)) {System.out.print(e +" ");}System.out.println();}}}
}

其中用到的IndexMinPQ见图解索引二叉堆

在一幅含有V个顶点和E条边的加权有向图中,使用Dijkstra算法计算根节点为给定起点的最短路径树所需的空间与V成正比,时间与ElogV成正比(最坏情况下)

图论算法——最短路径算法相关推荐

  1. 图论——networkx——最短路径算法篇

    NetworkX系列教程(10)-算法之一:最短路径问题 小书匠Graph图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的 ...

  2. 神经网络最短路径算法,最短路径算法的原理

    节约里程法求解最短路问题 你只要记住2点之间直线最短.节约里程法是用来解决运输车辆数目不确定的问题的最有名的启发式算法.1.节约里程法优化过程分为并行方式和串行方式两种. 核心思想是依次将运输问题中的 ...

  3. [算法]-最短路径算法总结

    Dijkstra最短路径算法 按路径长度的递增次序,逐步产生最短路径的贪心算法 基本思想:首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v 到其它各顶点的最短 ...

  4. 【老生谈算法】matlab实现最短路径算法——最短路径算法

    最短路径算法-matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]最短路径算法-matlab程序.doc 2.算 ...

  5. 【算法】弗洛伊德算法 最短路径算法

    文章目录 1.概述 2.图解 2.1 图示 2.2 弗洛伊德算法的步骤: 3.代码 1.概述 弗洛伊德(Floyd)算法介绍 和Dijkstra算法一 样,弗洛伊德(Floyd)算法也是一种用 于寻找 ...

  6. 弗洛伊德算法——最短路径算法

    弗洛伊德(Floyd)算法介绍 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算 ...

  7. 弗洛伊德算法-----最短路径算法(一)

    学习此算法的原因:昨天下午遛弯的时候,碰到闺蜜正在看算法,突然问我会不会弗洛伊德算法?我就顺道答应,然后用了半个小时的时间,学习了此算法,并用5分钟讲解给她听,在此也分享给各位需要的朋友,让你们在最短 ...

  8. 【算法】迪杰斯特拉算法 最短路径算法

    文章目录 1.概述 1.1 算法介绍 1.2 算法过程 2.代码 1.概述 太难了:https://www.bilibili.com/video/BV1E4411H73v?p=178 应用场景如下 战 ...

  9. 数据结构与算法--图论最短路径算法应用-词阶求解

    最短路径案例 词梯应用,在一个词梯中,每个单词均由前一个单词改变一个字母而得到.例如,我们通过一系列单字母替换而得到zero转换为five,如下:five:zero,hero,here,hire,fi ...

  10. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免

    文章出自:http://dsqiu.iteye.com/blog/1689163 最短路径算法--Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson,无一幸免 本 ...

最新文章

  1. Spring AOP切面的时候参数的传递
  2. Oracle PL/SQL块 多表查询(emp员工表、dept部门表、salgrade工资等级表)
  3. 基于 MVP 的 Android 组件化开发框架实践 1
  4. pythonobject转int_object怎么转换成float数据
  5. html标题居中加背景色,如何设置CSS背景宽度后让文字居中?
  6. CPA、CPS、CPC、CPM推广是什么意思?
  7. 一文带你了解推荐系统常用模型及框架
  8. Revel框架的搭建与部署教程
  9. 蚂蚁区块链使用搭建方法
  10. [JZOJ6347] 【NOIP2019模拟2019.9.8】ZYB玩字符串
  11. Linux_admin-练习
  12. 学习方法论与相关建议
  13. 区块链从业者地摊致富秘籍
  14. 超简单PictureSelector使用,从相册中选取多张图片并显示再列表中,微信样式,解决相册全白问题,可以拖拽删除并排序
  15. 科学计数法计算机怎么输,如何打印在Lua一个庞大的数字,而无需使用科学记数法?...
  16. 条码标签软件中如何在二维码输入汉字
  17. 羽素携手维琪共展科研实力,造护肤“芯”产链
  18. python随机函数random、画、星轨_教你绘制梵高的星空
  19. 【C语言中如何表示无穷大】
  20. i++和++i的区别

热门文章

  1. 阿里云ubuntu16.04安装ruby
  2. Hadoop原理深度剖析系列1——Hadoop的基本知识
  3. 将输入的字符串进行大写格式化
  4. 代码块(block)之函数体(二)
  5. 分享,用sql快速创建MODEL,快速提高工作效率哦
  6. gcc与g++编译器介绍
  7. C++编程语言中的值传递(pass-by-value)和引用传递(pass-by-reference)介绍
  8. 距离公式汇总以及Python实现
  9. 20172315 2017-2018-2 《程序设计与数据结构》实验三报告
  10. Python--网络编程-----通过socket收发文件软件开发--面向对象开发