这篇dijkstra算法写得比书上简单

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 Dijkstra算法 能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。

例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。

Dijkstra算法的迭代过程:

主题好好理解上图!

以下是具体的实现(C/C++):

[cpp]  view plain copy
  1. /*************************************** 
  2. * About:    有向图的Dijkstra算法实现 
  3. * Author:   Tanky Woo 
  4. * Blog:     www.WuTianQi.com 
  5. ***************************************/  
  6.    
  7. #include <iostream>  
  8. using namespace std;  
  9.    
  10. const int maxnum = 100;  
  11. const int maxint = 999999;  
  12.    
  13. // 各数组都从下标1开始  
  14. int dist[maxnum];     // 表示当前点到源点的最短路径长度  
  15. int prev[maxnum];     // 记录当前点的前一个结点  
  16. int c[maxnum][maxnum];   // 记录图的两点间路径长度  
  17. int n, line;             // 图的结点数和路径数  
  18.    
  19. // n -- n nodes  
  20. // v -- the source node  
  21. // dist[] -- the distance from the ith node to the source node  
  22. // prev[] -- the previous node of the ith node  
  23. // c[][] -- every two nodes' distance  
  24. void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])  
  25. {  
  26.     bool s[maxnum];    // 判断是否已存入该点到S集合中  
  27.     for(int i=1; i<=n; ++i)  
  28.     {  
  29.         dist[i] = c[v][i];  
  30.         s[i] = 0;     // 初始都未用过该点  
  31.         if(dist[i] == maxint)  
  32.             prev[i] = 0;  
  33.         else  
  34.             prev[i] = v;  
  35.     }  
  36.     dist[v] = 0;  
  37.     s[v] = 1;  
  38.    
  39.     // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中  
  40.     // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度  
  41.          // 注意是从第二个节点开始,第一个为源点  
  42.     for(int i=2; i<=n; ++i)  
  43.     {  
  44.         int tmp = maxint;  
  45.         int u = v;  
  46.         // 找出当前未使用的点j的dist[j]最小值  
  47.         for(int j=1; j<=n; ++j)  
  48.             if((!s[j]) && dist[j]<tmp)  
  49.             {  
  50.                 u = j;              // u保存当前邻接点中距离最小的点的号码  
  51.                 tmp = dist[j];  
  52.             }  
  53.         s[u] = 1;    // 表示u点已存入S集合中  
  54.    
  55.         // 更新dist  
  56.         for(int j=1; j<=n; ++j)  
  57.             if((!s[j]) && c[u][j]<maxint)  
  58.             {  
  59.                 int newdist = dist[u] + c[u][j];  
  60.                 if(newdist < dist[j])  
  61.                 {  
  62.                     dist[j] = newdist;  
  63.                     prev[j] = u;  
  64.                 }  
  65.             }  
  66.     }  
  67. }  
  68.    
  69. // 查找从源点v到终点u的路径,并输出  
  70. void searchPath(int *prev,int v, int u)  
  71. {  
  72.     int que[maxnum];  
  73.     int tot = 1;  
  74.     que[tot] = u;  
  75.     tot++;  
  76.     int tmp = prev[u];  
  77.     while(tmp != v)  
  78.     {  
  79.         que[tot] = tmp;  
  80.         tot++;  
  81.         tmp = prev[tmp];  
  82.     }  
  83.     que[tot] = v;  
  84.     for(int i=tot; i>=1; --i)  
  85.         if(i != 1)  
  86.             cout << que[i] << " -> ";  
  87.         else  
  88.             cout << que[i] << endl;  
  89. }  
  90.    
  91. int main()  
  92. {  
  93.     freopen("input.txt""r", stdin);  
  94.     // 各数组都从下标1开始  
  95.    
  96.     // 输入结点数  
  97.     cin >> n;  
  98.     // 输入路径数  
  99.     cin >> line;  
  100.     int p, q, len;          // 输入p, q两点及其路径长度  
  101.    
  102.     // 初始化c[][]为maxint  
  103.     for(int i=1; i<=n; ++i)  
  104.         for(int j=1; j<=n; ++j)  
  105.             c[i][j] = maxint;  
  106.    
  107.     for(int i=1; i<=line; ++i)    
  108.     {  
  109.         cin >> p >> q >> len;  
  110.         if(len < c[p][q])       // 有重边  
  111.         {  
  112.             c[p][q] = len;      // p指向q  
  113.             c[q][p] = len;      // q指向p,这样表示无向图  
  114.         }  
  115.     }  
  116.    
  117.     for(int i=1; i<=n; ++i)  
  118.         dist[i] = maxint;  
  119.     for(int i=1; i<=n; ++i)  
  120.     {  
  121.         for(int j=1; j<=n; ++j)  
  122.             printf("%8d", c[i][j]);  
  123.         printf("\n");  
  124.     }  
  125.    
  126.     Dijkstra(n, 1, dist, prev, c);  
  127.    
  128.     // 最短路径长度  
  129.     cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;  
  130.    
  131.     // 路径  
  132.     cout << "源点到最后一个顶点的路径为: ";  
  133.     searchPath(prev, 1, n);  
  134. }  

输入数据:
5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
输出数据:
999999 10 999999 30 100
10 999999 50 999999 999999
999999 50 999999 20 10
30 999999 20 999999 60
100 999999 10 60 999999
源点到最后一个顶点的最短路径长度: 60

 转载自: http://blog.csdn.net/startwithdp/article/details/8792536

明后两天挑时间写自己版本的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值