单源最短路径(Dijkstra)算法
来源:互联网 发布:忆江南的知作者怎么写 编辑:程序博客网 时间:2024/05/21 20:29
Dijkstra 算法是一种贪心算法。
假定源点为 u,顶点集合 V 被划分为两部分:S 和 V-S,其中 S中的顶点到源点的最短路径的长度已经确定,V-S中的顶点到源点的最短路径待定。
思想:
1. 每次从 V-S 中选择一个距离 源点最近的顶点,将其加入到 S 中,并从 V-S 中删除这个顶点;
2. 因为 S 中加入了新的顶点,更新 V-S 中其他所有点顶到源点的距离;
3. 当 V-S 为空时算法结束。
C++ 代码
#include <iostream>#include <limits>#include <vector>using namespace std;const int INFINITE = numeric_limits<int>::max();/* n:顶点个数(从 1 开始计数) * u:源点 * C:带权邻接矩阵 * dist:记录某顶点与源点 u 的最短路径长度 * p:记录某顶点到源点的最短路径上的该顶点的前驱顶点*/void Dijkstra(int n, int u, float *dist, int *p, int **C) { bool s[n];// 用于标记顶点是否加入了 S for(int i=1; i <= n; i++) { s[i] = false;// 处源点外,所有顶点都还未加入 S,在 V-S 中 dist[i] = C[u][i];// 初始化所有其他顶点到源点的距离 // 初始化所有其他顶点到源点的前驱 if(INFINITE == dist[i]) { p[i] = -1; } else { p[i] = u; } } s[u] = true;// 源点 u 默认加入 S dist[u] = 0;// 源点 u 到自己的距离为 0 for(int i=1; i <= n; i++) {// 遍历所有其他顶点 int minDist = INFINITE; int t = u; for(int j=1; j <= n; j++) {// 在 V-S 中寻找距离源点最近的点 t if(!s[j] && (dist[j]<minDist)) { t = j; minDist = dist[j]; } } if(t == u)// 表示剩余的顶点要么到源点不可达,要么已经全部找到了最短距离都加入到 S 了。 break; s[t] = true;// 找到这个顶点后,将其加入到 S for(int j=1; j <= n; j++) {// 因为有新的顶点加入到 S,故更新其他所有未加入的顶点(V-S中的顶点)到源点的距离和前驱 if(!s[j] && C[t][j]<INFINITE) if(dist[j] > (dist[t]+C[t][j])) { dist[j] = dist[t]+C[t][j]; p[j] = t; } } }}int** getMatC(int n, int m) {// 输入顶点个数,边个数,得到有向带权邻接矩阵 int **C = new int*[n+1]; for(int i=0; i <= n; i++) { C[i] = new int[n+1](); for(int j=0; j <= n; j++) if(i != j) C[i][j] = INFINITE; } for(int i=1; i <= m; i++) { int x, y; int distance = 0; cin >> x >> y >> distance; if(1 <= x && x <= n && 1 <= y && y <= n) C[x][y] = distance; } return C; // 输入样例:(有向带权图) // | 1 2 3 4 5 //--------------------- // 1 | 0 8 32 ∞ ∞ // 2 | 12 0 16 15 ∞ // 3 | ∞ 29 0 ∞ 13 // 4 | ∞ 21 ∞ 0 7 // 5 | ∞ ∞ 27 19 0 /* 即: 5 11 1 1 2 8 1 3 32 2 1 12 2 3 16 2 4 15 3 2 29 3 5 13 4 2 21 4 5 7 5 3 27 5 4 19 */}vector<int> getPath(int* p, int u, const int& v) { vector<int> path; path.push_back(v); int s = p[v]; while(s != u) { path.push_back(s); s = p[s]; } path.push_back(s); return path;}void printVec1D(const vector<int>& vec) { if(!vec.empty()) { for(int i = vec.size()-1; i > 0; i--) cout << vec[i] << " -> "; cout << vec[0] << endl; }}int main() { int n/*顶点数*/, m/*边数*/, u/*源点*/; cin >> n >> m >> u; int **C = getMatC(n, m); if(NULL != C) { float dist[n+1];// 存放距离 int path[n+1];// 存放前驱 Dijkstra(n, u, dist, path, C); for(int i=1; i <= n; i++) { if(INFINITE != dist[i]) { if(i != u) { cout << "顶点 " << u << " 到顶点 " << i << " 的距离是: " << dist[i] << endl; cout << "路径为:"; printVec1D(getPath(path, u, i)); } } else cout << "顶点 " << u << " 到顶点 " << i << " 不可达!" << endl; } } return 0;}
输入样例对应的输出结果:
2 0
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- 单源最短路径(Dijkstra算法)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- DijKstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- 单源最短路径(dijkstra算法)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- 单源最短路径(Dijkstra)算法
- Dijkstra算法(单源最短路径)
- Spark性能优化指南——高级篇
- 148. Linked List Random Node
- SQL分页优化
- emmc 命令协议
- Android的相对布局
- 单源最短路径(Dijkstra)算法
- 《JavaScript 操作 Cookie》
- 试验
- I/O篇(2)——I/O流体系简介
- 142. Linked List Cycle II
- MySQL学习笔记五
- 详解Ajax技术
- Retrofit2.0学习之Form-data传输
- javaScrfipt在各种浏览器中获取对象的方法