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

针对无向图,正权值路径,采取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. javascript下动态this与动态绑定实例代码

    this 的值取决于 function 被调用的方式,一共有四种, 如果一个 function 是一个对象的属性,该 funtion 被调用的时候,this 的值是这个对象. 如果 function ...

  2. CSS3鼠标移入移出图片生成随机动画

    今天分享使用html+css3+少量jquery实现鼠标移入移出图片生成随机动画,我们先看最终效果图(截图为静态效果,做出来可是动态的哟) 左右旋转 上下移动 缩放 由于时间关系我就不一步步解析各段代 ...

  3. The Unified Modeling Language(UML)

    统一过程建模语言UML 统一过程建模语言UML是一种标准的可视化建模语言,使用在:  业务建模和类似的过程 居于软件系统的分析.设计.和实现 UML 是一门通用语言,提供给业务分析员,软件架构师和开发 ...

  4. VS2010皮肤控件介绍

    在我们平时使用的各种工具中,如QQ,迅雷,以及各种空间等,都提供了一些换肤功能,可以让我们选择各种我们喜欢的界面.本文就对VS中常用的窗口程序做一个简单的换肤,利用一个dll文件来进行实现. 首先我们 ...

  5. Freemarker 对null值报错的处理

    忽略null值 假设前提:user.name为null ${user.name},异常 ${user.name!},显示空白 ${user.name!'vakin'},若user.name不为空则显示 ...

  6. Json 返回日期格式转换

    //日期转换 function ChangeDateFormat(time) { if (time != null) { var date = new Date(parseInt(time.repla ...

  7. nc 命令汇总

    转自: http://blog.chinaunix.net/uid-20068039-id-359170.html 1.远程拷贝文件从server1拷贝文件到server2上.需要先在server2上 ...

  8. SFTP文件上传与下载

    SFTP是对ftp进行加密的一种文件协议. 首先是先引入:jsch-0.1.42-sources.jar与jsch-0.1.42.jar包 SFTP文件上传与下载. import java.io.Fi ...

  9. ASP.NET MVC 增强Convert用法+【分页2】

    [分页2]    public dynamic PageQuery()        {              :  : ; i < data.Length; i++)            ...

  10. TeeChart的最小步长和最大步长

    /// <summary> /// 坐标轴的最大步长 /// </summary> public double MajorStep { get { return axis.Ca ...