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

    第09天 JDBC连接池&DBUtils工具类 今日内容介绍 u c3p0连接池 u dbcp连接池 u DBUtils工具类 第1章   c3p0连接池 1.1  连接池概述 实际开发中“获 ...

  2. android 发送url带中文出现乱码怎么解决

    上传的时候参数中带中文的时候发送参数的时候就有可能出现乱码,这种情况怎么解决呢,就是设置url的格式为utf-8 httpRequest.setEntity(new UrlEncodedFormEnt ...

  3. 牛客网2018暑期训练 第三场 a题

    #include <bits/stdc++.h> using namespace std; vector<int> path; ; short dp[maxn][maxn][m ...

  4. UIKit Dynamic主题学习笔记

    1.重力效果:UIGravityBehavior @IBOutlet weak var frogImage: UIImageView! //创建一个关联到view的动画(必须为全局变量) lazy v ...

  5. 使用nohup后台执行ftp传输命令

    因为有的时候会需要长时间传输文件,所以想用nohup 结合shell脚本一起使用,就不用一直在电脑面前了 . nohup 用法: nohup command & 然后就会出现 对应的 pid ...

  6. [NewCode 4] 替换空格

    题目描述 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 最直接的方式, ...

  7. Gimp RGB 转 CMYK

    安装GIMP separate+插件.在Windows的Photoshop中,有转换CMYK的功能,非常简单.在Linux里,通常用GIMP进行转换.由于授权的问题,默认安装的GIMP里没有安装转换的 ...

  8. headpq

    从一个集合中获得最大或者最小的N个元素列表 http://python3-cookbook.readthedocs.io/zh_CN/latest/c01/p04_find_largest_or_sm ...

  9. 检查.net dll构建的目标平台是any cpu、x86、x64

    有时候,需要检查构建的dll是否针对正确的平台 可以使用CorFlags.exe(它是.NET Framework SDK的一部分)从dll中查找此信息.运行CorFlags.exe将产生以下输出: ...

  10. 使用WPF制作视频监控多画面切换

    前言 曾有做过一个产品,有一个功能是视频监控模块,视频监控首先想到的是视频多画面切换功能,由于前端是用WPF开发的,所以当时就做了一个多画面切换组件,效果如下: 功能设计前提: 由于要使用海康大华天地 ...