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

针对无向图,正权值路径,采取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. CentOS安装+配置+远程

    这篇博客我之前写在了csdn,转了过来,这篇是自己认为写的比较有技术含量的文章^_^ 最近和CentOS打了交到,其中遇到了很多问题,于是看了一些博客,解决了一些问题,但是都不是特别全面,所以想来一篇 ...

  2. AS3.0的动态类和密封类

    动态类:生成的实例可以在运行时动态添加属性和方法.类名前有dynamic就是动态类 密封类:生成的实例不可以在运行时动态添加属性和方法

  3. 格式化分区,报/dev/sdb1 is apparently in use by the system; will not make a filesystem here!

    [root@RAC2 ~]# mke2fs /dev/sdb1mke2fs 1.39 (29-May-2006)/dev/sdb1 is apparently in use by the system ...

  4. ARM 的Thumb状态测试

    作为一个使用ARM的学习者,有必要全面了解你的处理器内核.尽管有些内容可能在实际应用中用不到,但是“了解”还是很必要的.Thumb状态,是ARM的一个特色,但是你知道Thumb状态与ARM状态最大的区 ...

  5. asp.net mvc 发送邮箱验证码

    public ActionResult Index() { /*第一种,利用Google的smtp来发送邮件*/ SmtpClient client = ); Random Rdm = new Ran ...

  6. iphone 屏幕投射到Mac上

    在实际的工作中,我们往往需要演示iPhone上面的程序,但是由于手机屏幕太小,无法同时给很多人看,这时候就需要进行屏幕投射.目前我需要实现的是投射到Mac上.我使用有线USB和无线Airplay两种方 ...

  7. AppStore IPv6-only审核被拒原因分析及解决方案-b

    自2016年6月1日起,苹果要求所有提交App Store的iOS应用必须支持IPv6-only环境,背景也是众所周知的,IPv4地址已基本分配完毕,同时IPv6比IPv4也更加高效,向IPv6过渡是 ...

  8. Computer Vision Applied to Super Resolution

    Capel, David, and Andrew Zisserman. "Computer vision applied to super resolution." Signal ...

  9. NOI冲刺计划

    省选过了,剩下大概是NOI冲刺了吧.中间还有一大堆诸如会考,CTSC,APIO等东西. 最近先不急着天天刷八中了吧,多在不同网站见一些题,然后再着重提高一下代码准确性.重点把DP这个板块多练习一下,八 ...

  10. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...