最短路径算法----Dijkstra

最近上图论,学了单源最短路径的Dijkstra算法。

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

老师只字不提思想,硬分析过程还是有点@#$%的。

结果就是,原先我还挺懂的,听完就凌乱了。

 

在这里写一下吧

=================================================

参考资料:

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

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

CLRS

《算法设计与分析》

=================================================

算法流程:

在以下说明中,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 }

 

 

 

 

posted @ 2012-05-15 12:23  漂木  阅读(2637)  评论(0编辑  收藏  举报