Dijkstra算法的核心思想是贪心策略+动态规划

算法流程:

在以下说明中,s为源,w[u,v]为点u和v之间的边的长度,结果保存在dis[]

初始化:源的距离dis[s]设为0,其他的点距离设为无穷大(实际程序里设成-1了),同时把所有的点的状态设为没有扩展过。

循环n-1次:

  1. 在没有扩展过的点中取一距离最小的点u,并将其状态设为已扩展。
  2. 对于每个与u相邻的点v,执行Relax(u,v),也就是说,如果dis[u]+map[u,v]<dis[v],那么把dis[v]更新成更短的距离dis[u]+w[u,v]。此时到点v的最短路径上,前一个节点即为u。
  3. 结束。此时对于任意的u,dis[u]就是s到u的距离。

wiki上有个很好的图,可以帮助理解算法过程:

测试数据来自清华的紫皮算法书,如下:

迭代过程如下:

迭代

S

U

dis[2]

dis[3]

dis[4]

dis[5]

初始

{1}

---

10

-1

30

100

1

{1,2}

2

10

60

30

100

2

{1,2,4}

4

10

50

30

90

3

{1,2,4,3}

3

10

50

30

60

4

{1,2,4,3,5}

5

10

50

30

60

看上面的两个图,基本就能把Dijkstra算法的具体过程了解清楚。

算法正确性证明可以看Wiki和CLRS。

程序如下(测试数据就是上面的,输出了6个结果):

int dijk(int s, int e);函数返回从s到e的最短路。

  1. 1 #include <stdio.h>
  2. 2 #include <limits.h>
  3. 3 #include <string.h>
  4. 4
  5. 5 const int n = 6;
  6. 6 int map[n][n];
  7. 7
  8. 8 int dijk(int s, int e)
  9. 9 {
  10. 10 int dis[n];
  11. 11 int used[n] = {0};
  12. 12 int min, next;
  13. 13 memset(dis, 255, sizeof(dis));//把所有未更新的dis[]设置成-1
  14. 14
  15. 15 dis[s] = 0; //从s开始
  16. 16
  17. 17 for (int i=1; i<n; ++i)
  18. 18 {
  19. 19 min = INT_MAX;
  20. 20 for (int j=1; j<n; ++j)
  21. 21 {
  22. 22 if (!used[j] && dis[j]!=-1 && dis[j]<min)
  23. 23 {
  24. 24 min = dis[j];
  25. 25 next = j;
  26. 26 }
  27. 27 }
  28. 28 if (min != INT_MAX)
  29. 29 {
  30. 30 used[next] = 1;
  31. 31 for (int j=1; j<n; ++j)
  32. 32 {
  33. 33 if (!used[j] && map[next][j]!=-1 &&
  34. 34 (dis[j]>map[next][j]+dis[next] || dis[j]==-1))
  35. 35 {
  36. 36 dis[j] = map[next][j] + dis[next];
  37. 37 }
  38. 38 }
  39. 39 }
  40. 40 }
  41. 41 return dis[e];
  42. 42 }
  43. 43
  44. 44
  45. 45 int main()
  46. 46 {
  47. 47 for (int i=1; i<n; ++i)
  48. 48 {
  49. 49 for (int j=1; j<n; ++j)
  50. 50 {
  51. 51 map[i][j] = -1;
  52. 52 }
  53. 53 }
  54. 54
  55. 55 map[1][2] = 10;
  56. 56 map[1][4] = 30;
  57. 57 map[1][5] = 100;
  58. 58 map[2][3] = 50;
  59. 59 map[3][5] = 10;
  60. 60 map[4][3] = 20;
  61. 61 map[4][5] = 60;
  62. 62   
  63. 63 printf("%d %d %d %d %d %d\n", dijk(1, 5), dijk(2, 3), dijk(1, 5), dijk(4, 5), dijk(1, 2), dijk(2, 4));
  64. 64
  65. 65
  66. 66 return 0;
  67. 67 }
  1. 1 /*Dijkstra求单源最短路径 2010.8.26*/
  2. 2
  3. 3 #include <iostream>
  4. 4 #include<stack>
  5. 5 #define M 100
  6. 6 #define N 100
  7. 7 usingnamespace std;
  8. 8
  9. 9 typedef struct node
  10. 10 {
  11. 11 int matrix[N][M]; //邻接矩阵
  12. 12 int n; //顶点数
  13. 13 int e; //边数
  14. 14 }MGraph;
  15. 15
  16. 16 void DijkstraPath(MGraph g,int*dist,int*path,int v0) //v0表示源顶点
  17. 17 {
  18. 18 int i,j,k;
  19. 19 bool*visited=(bool*)malloc(sizeof(bool)*g.n);
  20. 20 for(i=0;i<g.n;i++) //初始化
  21. 21 {
  22. 22 if(g.matrix[v0][i]>0&&i!=v0)
  23. 23 {
  24. 24 dist[i]=g.matrix[v0][i];
  25. 25 path[i]=v0; //path记录最短路径上从v0到i的前一个顶点
  26. 26 }
  27. 27 else
  28. 28 {
  29. 29 dist[i]=INT_MAX; //若i不与v0直接相邻,则权值置为无穷大
  30. 30 path[i]=-1;
  31. 31 }
  32. 32 visited[i]=false;
  33. 33 path[v0]=v0;
  34. 34 dist[v0]=0;
  35. 35 }
  36. 36 visited[v0]=true;
  37. 37 for(i=1;i<g.n;i++) //循环扩展n-1次
  38. 38 {
  39. 39 int min=INT_MAX;
  40. 40 int u;
  41. 41 for(j=0;j<g.n;j++) //寻找未被扩展的权值最小的顶点
  42. 42 {
  43. 43 if(visited[j]==false&&dist[j]<min)
  44. 44 {
  45. 45 min=dist[j];
  46. 46 u=j;
  47. 47 }
  48. 48 }
  49. 49 visited[u]=true;
  50. 50 for(k=0;k<g.n;k++) //更新dist数组的值和路径的值
  51. 51 {
  52. 52 if(visited[k]==false&&g.matrix[u][k]>0&&min+g.matrix[u][k]<dist[k])
  53. 53 {
  54. 54 dist[k]=min+g.matrix[u][k];
  55. 55 path[k]=u;
  56. 56 }
  57. 57 }
  58. 58 }
  59. 59 }
  60. 60
  61. 61 void showPath(int*path,int v,int v0) //打印最短路径上的各个顶点
  62. 62 {
  63. 63 stack<int> s;
  64. 64 int u=v;
  65. 65 while(v!=v0)
  66. 66 {
  67. 67 s.push(v);
  68. 68 v=path[v];
  69. 69 }
  70. 70 s.push(v);
  71. 71 while(!s.empty())
  72. 72 {
  73. 73 cout<<s.top()<<"";
  74. 74 s.pop();
  75. 75 }
  76. 76 }
  77. 77
  78. 78 int main(int argc, char*argv[])
  79. 79 {
  80. 80 int n,e; //表示输入的顶点数和边数
  81. 81 while(cin>>e>>n&&e!=0)
  82. 82 {
  83. 83 int i,j;
  84. 84 int s,t,w; //表示存在一条边s->t,q权值为w
  85. 85 MGraph g;
  86. 86 int v0;
  87. 87 int*dist=(int*)malloc(sizeof(int)*n);
  88. 88 int*path=(int*)malloc(sizeof(int)*n);
  89. 89 for(i=0;i<N;i++)
  90. 90 for(j=0;j<M;j++)
  91. 91 g.matrix[i][j]=0;
  92. 92 g.n=n;
  93. 93 g.e=e;
  94. 94 for(i=0;i<e;i++)
  95. 95 {
  96. 96 cin>>s>>t>>w;
  97. 97 g.matrix[s][t]=w;
  98. 98 }
  99. 99 cin>>v0; //输入源顶点
  100. 100 DijkstraPath(g,dist,path,v0);
  101. 101 for(i=0;i<n;i++)
  102. 102 {
  103. 103 if(i!=v0)
  104. 104 {
  105. 105 showPath(path,i,v0);
  106. 106 cout<<dist[i]<<endl;
  107. 107 }
  108. 108 }
  109. 109 }
  110. 110 return0;
  111. 111 }

参考资料:

Wikipedia:http://en.wikipedia.org/wiki/Dijkstra's_algorithm

Nocow:http://www.nocow.cn/index.php/Dijkstra%E7%AE%97%E6%B3%95

CLRS

《算法设计与分析》

(转)http://www.cnblogs.com/rootjie/archive/2012/05/15/2501317.html

最短路径算法----Dijkstra (转)的更多相关文章

  1. 最短路径算法Dijkstra和A*

    在设计基于地图的游戏,特别是isometric斜45度视角游戏时,几乎必须要用到最短路径算法.Dijkstra算法是寻找当前最优路径(距离原点最近),如果遇到更短的路径,则修改路径(边松弛). Ast ...

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

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

  3. 有向有权图的最短路径算法--Dijkstra算法

    Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...

  4. 带权图的最短路径算法(Dijkstra)实现

    一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...

  5. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson

    根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...

  6. 最短路径算法——Dijkstra算法

    在路由选择算法中都要用到求最短路径算法.最出名的求最短路径算法有两个,即Bellman-Ford算法和Dijkstra算法.这两种算法的思路不同,但得出的结果是相同的. 下面只介绍Dijkstra算法 ...

  7. 最短路径算法——Dijkstra算法与Floyd算法

    转自:https://www.cnblogs.com/smile233/p/8303673.html 最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2  ...

  8. 最短路径算法-Dijkstra

    Dijkstra是解决单源最短路径的一般方法,属于一种贪婪算法. 所谓单源最短路径是指在一个赋权有向图中,从某一点出发,到另一点的最短路径. 以python代码为例,实现Dijkstra算法 1.数据 ...

  9. 单源最短路径算法---Dijkstra

    Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路 ...

  10. 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)

    Dijkstra算法 ———————————最后更新时间:2011.9.25———————————Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径. ...

随机推荐

  1. Django URLs error: view must be a callable or a list/tuple in the case of include()

    Django 1.10 no longer allows you to specify views as a string (e.g. 'myapp.views.home') in your URL ...

  2. 第88讲:Scala中使用For表达式实现map、flatMap、filter

    今天我们来学习一下如何使用for表达式实现map.flatMap以及filter 首先,我们来看下map.map的功能是,传入一个list,通过一个函数f,将list中的元素A变成元素B的过程.最后得 ...

  3. Java 理论与实践: 用弱引用堵住内存泄漏

    弱引用使得表达对象生命周期关系变得容易了 虽然用 Java™ 语言编写的程序在理论上是不会出现“内存泄漏”的,但是有时对象在不再作为程序的逻辑状态的一部分之后仍然不被垃圾收集.本月,负责保障应用程序健 ...

  4. 第三天:DOM操作css

    基本语法: 引用样式时是在head中,用link,另外需要<div>才能显示 修改样式:按下按钮后,引用的样式部分,颜色变为蓝色 如图下图是更改了样式中hello的颜色 代码如下: < ...

  5. 转:iOS9的新特性以及适配方案

    2015年9月8日,苹果宣布iOS 9操作系统的正式版在太平洋时间9月16日正式推出,北京时间9月17日凌晨1点推送. 新的iOS 9系统比iOS8更稳定,功能更全面,而且还更加开放.iOS 9加入了 ...

  6. 【转】jQuery.validate 用法

    名称                              返回类型                描述 validate(options)          返回:Validator       ...

  7. 6.翻译:EF基础系列---什么是EF中的实体?

    原文地址:http://www.entityframeworktutorial.net/basics/what-is-entity-in-entityframework.aspx EF中的实体就是继承 ...

  8. AJPFX:外汇的技术面分析

    AJPFX平台:开设外汇保证金交易账户以及入金之后,通常就可以开始交易了,但是在选择买卖时点时通常会依据两种分析,两种主要分析方法通常会被称为基本面分析和技术分析.基本面分析注重金融,经济理论和政局发 ...

  9. 写vue项目时候 零星的笔记

    1,挂载也可以用 .$mount() 2,子组件中通过this.$root拿到实例的数据.截图中是子组件中

  10. linux防火墙(三)—— iptables语法之匹配条件

    一.iptables规则的匹配条件类型有三类 1.通用匹配:可直接使用,不依赖于其他条件或扩展,包括网络协议.IP地址.网络接口等条件 2.隐含匹配:要求以特定的协议匹配作为前提,包括端口.TCP标记 ...