最短路径是图论算法中的经典问题。图分为有向图、无向图,路径权值有正值、负值,针对不同的情况需要分别选用不同的算法。在维基上面给出了各种不同的场景应用不同的算法的基本原则:最短路问题

针对无向图,正权值路径,采取Dijkstra算法

如上图,是求a到b的最短路径,这里并不限定b节点,修改为到任意节点的路径,问题是完全一样的。

首先需要记录每个点到原点的距离,这个距离会在每一轮遍历的过程中刷新。每一个节点到原点的最短路径是其上一个节点(前驱节点)到原点的最短路径加上前驱节点到该节点的距离。以这个原则,经过N轮计算就能得到每一个节点的最短距离。

第一轮,可以计算出,2、3、4、5、6到原点1的距离分别为:[7, 9, -1, -1, 14]。-1表示无穷大。取其中最小的,为7,即可以确定1的最短路径为0,2为下一轮的前驱节点。同时确定2节点的最短路径为7,路线:1->2。

第二轮,取2节点为前驱节点,按照前驱节点的最短距离加上该节点与前驱节点的距离计算新的最短距离,可以得到3,4,5,6节点到原点的距离为:[17, 22, -1, -1],此时需要将这一轮得到的结果与上一轮的比较,3节点:17 > 9,最短路径仍然为9;4节点:22 < 无穷大,刷新4节点的最短路径为22;5节点:不变,仍然为无穷大;6节点:14 < 无穷大,取14,不变。则可以得到本轮的最短距离为:[9, 22, -1, 14],取最短路径最小的节点,为3,作为下一轮的前驱节点。同时确定3节点的最短路径为9,路线:1->3。

第三轮,同上,以3为前驱节点,得到4,5,6的计算距离为:[20, -1, 11],按照取最短路径的原则,与上一轮的进行比较,刷新为:[20, -1, 11],选定6为下一轮的前驱节点。同时取定6的最短路径为11,路线:1->3->6。

第四轮,同上,以6为前驱节点,得到4和5的计算距离为[20, 20],与上一轮进行比较,刷新后为[20, 20],二者相等只剩下两个节点,并且二者想等,剩下的计算已经不需要了。则两个节点的最短路径都为20。整个计算结束。4的最短路径为20,路线:1->3->4。5的最短路径为20,路线:1->3->6->5。

如果二者不相等,则还需要进行第五轮,先确定二者中的一个的最短路径和路线,再取定剩下的。直到整个5次循环都完成。

结合上面的文字,算法的伪代码比较好理解,但是翻译成代码还是有一点麻烦:

function Dijkstra(G, w, s)
   for each vertex v in V[G]         //初始化
         d[v] := infinity             // 將各點的已知最短距離先設成無窮大
         previous[v] := undefined     // 各点的已知最短路径上的前趋都未知
   d[s] := 0                         // 因为出发点到出发点间不需移动任何距离,所以可以直接将s到s的最小距离设为0
   S := empty set
   Q := set of all vertices
   while Q is not an empty set       // Dijkstra演算法主體
         u := Extract_Min(Q)
         S.append(u)
         for each edge outgoing from u as (u,v)
                if d[v] > d[u] + w(u,v)       // 拓展边(u,v)。w(u,v)为从u到v的路径长度。
                      d[v] := d[u] + w(u,v)   // 更新路径长度到更小的那个和值。
                      previous[v] := u        // 紀錄前趨頂點

翻译成代码,则还有一些复杂。

Extract_Min(Q)方法就是从顶点集合中删除掉距离最小的点,并确定该节点的最短距离和路线。这里给出求最短距离的代码,具体的路径记录还没有比较简洁的思路实现。后面有空再来补充。

public class Dijkstra
   {

       public static final int M = -1;

       public static void main(String[] args)

       {

           int[][] map1 = {

                   { 0,  7,  9,  M,  M, 14 },

                   { 7,  0,  10, 15, M, M },

                   { 9,  10, 0,  11, M, 2 },

                   { M,  15, 11, 0,  6, M },

                   { M,  M,  M,  6,  0, 9 },

                   { 14, M,  2,  M,  9, 0 } };

           int orig = 0;

           int[] shortPath = Dijsktra(map1, orig);

           if (shortPath == null)

           {

               return;

           }

           for (int i = 0; i < shortPath.length; i++)

           {

               System.out.println("从" + (orig + 1) + "出发到" + (i + 1) + "的最短距离为:"

                       + shortPath[i]);

           }

       }

       public static int[] Dijsktra(int[][] weight, int orig)

       {

           int n = weight.length;              // 顶点个数

           int[] shortest = new int[n];        // 存放从start到其他各点的最短路径

           boolean[] visited = new boolean[n]; // 标记当前该顶点的最短路径是否已经求出,true表示已求出

           // 初始化,第一个顶点求出

           shortest[orig] = 0;

           visited[orig] = true;

           for (int count = 0; count != n - 1; count++) // 要加入n-1个顶点

           {

               // 选出一个距离初始顶点最近的未标记顶点

               int k = M;    

               int dmin = M;

               for (int i = 0; i < n; i++)

               {

                   if (!visited[i] && weight[orig][i] != M)

                   {

                        if (dmin == -1 || dmin > weight[orig][i])

                        {

                            dmin = weight[orig][i];

                            k = i;

                        }

                   }

               }

               // 正确的图生成的矩阵不可能出现K == M的情况

               if (k == M)

               {

                   System.out.println("the input map matrix is wrong!");

                   return null;

               }

               shortest[k] = dmin;

               visited[k] = true;

               // 以k为中间点,修正从原点到未访问各点的距离

               for (int i = 0; i < n; i++)

               {

                   if (!visited[i] && weight[k][i] != M)

                   {

                       int callen = dmin + weight[k][i];

                       if (weight[orig][i] == M || weight[orig][i] > callen)

                       {

                           weight[orig][i] = callen;

                       }

                   }

               }

           }

           return shortest;

       }

   }

Dijkstra算法求解最短路径分析的更多相关文章

  1. python利用dijkstra算法求解图中最短距离

    利用dijkstra算法,来完成图中两个顶点间最短的距离,可以直接复制使用,只需要修改参数即可 def dijkstra_raw(edges, from_node, to_node): "& ...

  2. JAVA之单源最短路径(Single Source Shortest Path,SSSP问题)dijkstra算法求解

    题目简介:给定一个带权有向图,再给定图中一个顶点(源点),求该点到其他所有点的最短距离,称为单源最短路径问题. 如下图,求点1到其他各点的最短距离 准备工作:以下为该题所需要用到的数据 int N; ...

  3. POJ 3268 Silver Cow Party(Dijkstra算法求解来回最短路问题)

    题目链接: https://vjudge.net/problem/POJ-3268 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently n ...

  4. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

  5. 单源最短路径问题之dijkstra算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...

  6. 非负权值有向图上的单源最短路径算法之Dijkstra算法

    问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...

  7. 有向网络(带权的有向图)的最短路径Dijkstra算法

    什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点 ...

  8. 数据结构与算法系列研究七——图、prim算法、dijkstra算法

    图.prim算法.dijkstra算法 1. 图的定义 图(Graph)可以简单表示为G=<V, E>,其中V称为顶点(vertex)集合,E称为边(edge)集合.图论中的图(graph ...

  9. python代码实现dijkstra算法

    求解从1到6的最短路径. python代码实现:(以A-F代表1-6) # Dijkstra算法需要三张散列表和一个存储列表用于记录处理过的节点,如下: processed = [] def buil ...

随机推荐

  1. samba和squid 安装

    一. samba配置1. 什么是sambaSamba服务类似于windows上的共享功能,可以实现在Linux上共享文件,windows上访问,当然在Linux上也可以访问到.是一种在局域网上共享文件 ...

  2. winform模拟鼠标按键

    今天朋友说被他们公司的学习网站恶心到了,下班后要他看学习资料,看完点下一页,而且一页必须停留多少时间才能点击下一页,想不看都不行,于是晚上我突发奇想要给他做一个模拟鼠标按键的程序,可以让鼠标定时间隔触 ...

  3. DISC免费性格测试题

    现在给大家推荐一款世界500强和猎头公司招聘人才时用的DISC性格测评,用在找对象方面也比较合适.大家不妨看下自己的性格,就知道该找什么样的意中人啦--- 在每一个大标题中的四个选择题中只选择一个最符 ...

  4. 《Excel图表之道》读书笔记

    一.突破常规的作图方法 突破Excel的默认颜色 非数据元素用淡色 突破Excel的图表布局 图表要素:主标题.副标题.图例.绘图.脚注 竖向构图 标明数据来源.图表注释.坐标轴截断符号 专业的水蓝色 ...

  5. TDirectory.GetLogicalDrives获取本地逻辑驱动器

    使用函数: System.IOUtils.TDirectory.GetLogicalDrives class function GetLogicalDrives: TStringDynArray; s ...

  6. 未能解析此远程名称:'nuget.org'

    今天用Nuget下一个程序包时,发现Nuget挂了:未能解析此远程名称:'nuget.org'.第一反应就是方校长抖威风了,挂个代理上 http://nuget.org 试了下,果然好好的. 用命令n ...

  7. Python的面向对象4

    今天我们接着来聊聊继承! 那什么是继承呢? 新写的类是不必重新编写,只要从现有的类继承,就自动拥有了该类的所有功能,新类只需要编写现有类缺少的功能,可以复用已有的代码! python的继承的特点: 继 ...

  8. 4070: [Apio2015]雅加达的摩天楼

    Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼.   有 M 只叫做 “do ...

  9. ▲历史回眸--abbr和acronym的渊源

    网景和微软的浏览器之战早已淡去多年,最终以微软的IE浏览器胜出,特别是IE6的出现,一度成为世界浏览器的霸主,至今无人能敌.去年IE6荣获“终身成就奖”,真是实至名归.本文涉及的两个标签abbr和ac ...

  10. java 常用基本数据类型的默认值

    在使用基本数据类型作为类成员的时候,有时只初始化了而没有给变量赋值,那么此时,java会给你的变量赋一个默认初始值. boolean        false char              '/ ...