单源点最短路径算法(dijkstra)
2013-10-24 22:11
225 查看
问题描述:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。
算法思想:Dijkstra提出了一个按路径长度递增的次序产生最短路径的算法。首先,引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从源点v到每个终点vi的最短路径长度。它的初始状态为:若v到vi有弧,则D[i]为弧上的权值,否则D[i]为无穷大。显然,长度为:
D[j] = Min{D[i] | vi 属于V}
的路径就是从v出发的长度最短的一条路径。此路径为 (v, vi)。 那么,长度次短的路径是哪一条呢?假设该次短路径的终点是vk,则可以证明,这条路径或者是(v, vk),或者是(v, vj, vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。
一般情况下,假设S为已经求得最短路径的终点的集合,则可证明:下一条最短路径(假设其终点为x)或者是弧(v, x),或者是中间只经过S中的顶点而最后到达顶点x的路径。这可以用反证法来证明。假设此路径上有一个顶点不在S中,则说明存在一条终点不在S而长度比此路径短的路径。但是这是不可能的,因为我们是按路径长度递增的次序来产生最短路径的,长度比此路径短的所有路径均已产生,它们的终点必定在S中,假设不成立。
假设有向图如下:
求源点v0到其余各顶点的最短路径。
c++语言实现:
为什么只用一个Path数组就可以记录到所有终点的最短路径呢?因为这里Path[i]表示终点为vi的最短路径中vi的前驱节点。假设终点vi的前驱节点为vj,则到终点vi的路径一定是先到vj,然后通过弧(vj, vi)到vi。所以Path只需要记录每个节点的前驱节点即可。Path[i]需初始化为源点。
算法思想:Dijkstra提出了一个按路径长度递增的次序产生最短路径的算法。首先,引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从源点v到每个终点vi的最短路径长度。它的初始状态为:若v到vi有弧,则D[i]为弧上的权值,否则D[i]为无穷大。显然,长度为:
D[j] = Min{D[i] | vi 属于V}
的路径就是从v出发的长度最短的一条路径。此路径为 (v, vi)。 那么,长度次短的路径是哪一条呢?假设该次短路径的终点是vk,则可以证明,这条路径或者是(v, vk),或者是(v, vj, vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。
一般情况下,假设S为已经求得最短路径的终点的集合,则可证明:下一条最短路径(假设其终点为x)或者是弧(v, x),或者是中间只经过S中的顶点而最后到达顶点x的路径。这可以用反证法来证明。假设此路径上有一个顶点不在S中,则说明存在一条终点不在S而长度比此路径短的路径。但是这是不可能的,因为我们是按路径长度递增的次序来产生最短路径的,长度比此路径短的所有路径均已产生,它们的终点必定在S中,假设不成立。
假设有向图如下:
求源点v0到其余各顶点的最短路径。
c++语言实现:
#include <iostream> using namespace std; const int MAX = 0x7fffffff; //定义无穷大 const int NUM_VERTEX = 6; //图中节点个数 // 图的邻接矩阵表示 int g_graph[6][6] = {0, MAX, 10, MAX, 30, 100, MAX, 0, 5, MAX, MAX, MAX, MAX, MAX, 0, 50, MAX, MAX, MAX, MAX, MAX, 0, MAX, 10, MAX, MAX, MAX, 20, 0, 60, MAX, MAX, MAX, MAX, MAX, 0}; long long Dist[NUM_VERTEX]; //辅助数组,记录当前v到各点vi的最短距离 int Path[NUM_VERTEX]; //保存最短路径 bool Final[NUM_VERTEX]; //保存已经求得的最短路径的终点集合 // srcVertex为源点编号 void dijkstra(int srcVertex){ for (int i = 0; i < NUM_VERTEX; i++){ Dist[i] = g_graph[srcVertex][i]; Final[i] = false; Path[i] = srcVertex; } Final[srcVertex] = true; for (int i = 0; i < NUM_VERTEX; i++){ long long min = MAX; int v = -1; for (int j = 0; j < NUM_VERTEX; j++){ if (!Final[j] && Dist[j] < min){ min = Dist[j]; v = j; } } if (v == -1) break; Final[v] = true; for (int k = 0; k < NUM_VERTEX; k++){ if (!Final[k] && Dist[v] + g_graph[v][k] < Dist[k]){ Dist[k] = Dist[v] + g_graph[v][k]; Path[k] = v; } } } } // 测试 int main(){ int srcVertex = 0; dijkstra(srcVertex); for (int i = 0; i < NUM_VERTEX; i++){ if (Dist[i] < MAX){ cout << i << ": " << Dist[i] << " "; int k = i; cout << "reverse path: " << i << " "; while (k != srcVertex){ cout << Path[k] << " "; k = Path[k]; } cout << endl; } else{ cout << i << ": " << "No Path" << endl; } } return 0; }
为什么只用一个Path数组就可以记录到所有终点的最短路径呢?因为这里Path[i]表示终点为vi的最短路径中vi的前驱节点。假设终点vi的前驱节点为vj,则到终点vi的路径一定是先到vj,然后通过弧(vj, vi)到vi。所以Path只需要记录每个节点的前驱节点即可。Path[i]需初始化为源点。
相关文章推荐
- 一个例子让你明白一个算法-Dijkstra(求源点到各顶点最短路径)
- 贪心算法 Dijkstra 单源最短路径
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 算法导论-第24章- 单源最短路径 - 24.3 Dijkstra 算法
- 最短路径算法(Dijkstra、Floyd)总结
- 算法学习笔记——Dijkstra单源最短路径算法
- 算法与数据结构-单源最短路径之Dijkstra
- <菜鸟学算法-Dijkstra求最短路径>
- DIJKSTRA最短路径算法
- Dijkstra最短路径算法
- hdu-1385 Minimum Transport Cost(Dijkstra最短路径算法)
- 最短路径算法Dijkstra algorithm
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 图论最短路径算法——Dijkstra
- Dijkstra和Floyd算法----最短路径算法
- 带权图最短路径 Dijkstra 算法和实现
- HDU 2112 HDU Today,最短路径算法,Dijkstra
- 最短路径算法Dijkstra和A*
- 【算法】最短路径之Dijkstra(II)
- 最短路径算法之 Dijkstra(迪杰斯特拉)算法