Dijkstra 算法的 C/C++ 实现
2016-08-28 18:47
525 查看
Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,是广度优先算法的一种,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离。当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性。不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破坏了已经更新的点距离不会改变的性质。
Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
Dijkstra 算法的时间复杂度为O(n^2) 空间复杂度取决于存储方式,邻接矩阵为O(n^2)
先上代码:
假设我们的测试用例如下图所示:
我们以A作为起始顶点,计算A到每个顶点的最短路径,注意,这是一幅带权图,图的邻接矩阵表示如下:
计算结果如下:
Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
Dijkstra 算法的时间复杂度为O(n^2) 空间复杂度取决于存储方式,邻接矩阵为O(n^2)
先上代码:
// Dijkstra.cpp : 定义控制台应用程序的入口点。 // #include <stdio.h> #include <vector> #include <iostream> using namespace::std; #define INF 0x7fffffff #define maxN 50 #pragma warning(disable:4996) #define USE_C 1 #define NOT_USE_C 0 #define USE_CPP 1 int matrix[maxN][maxN]; // C++实现 void Dijkstra_cpp(vector<vector<int>>&vec, vector<int>& result, int v0){ vector<int> visited(vec.size(), 0); // 表示顶点是否被选中,0:顶点未被选中;1:顶点已被选中 int last_visited = 0; visited[v0] = 1; // 选中起始顶点 result[0] = 0; for (int i = 0; i < vec.size() - 1; ++i) { // N 个顶点需要做 N - 1 次循环 // 查看顶点周围的所有点 for (int j = 0; j < vec.size(); ++j) { // 循环遍历所有顶点 if (visited[j] == 0){ // 保证被查看的新顶点没有被访问到 if (vec[v0][j] != 0){ // 保证当前顶点(V0)与新顶点(j)之间有路径 int dist = vec[v0][j] + last_visited; // 计算 V0 到 J 的路径距离 if (dist < result[j])result[j] = dist; // 用新路径代替原来的路径 } } } // 找出最小值 int minIndex = 0; while (visited[minIndex] == 1) minIndex++; // 找第一个没有被选中的节点 for (int j = minIndex; j < vec.size(); ++j) { if (visited[j] == 0 && result[j] < result[minIndex]){ minIndex = j; } } last_visited = result[minIndex]; // 更新最小值 visited[minIndex] = 1; // 将最小值顶点选中 v0 = minIndex; // 下次查找从最限制顶点开始 } } // C语言实现 void Dijkstra_c(int out[], int N, int v0){ int i, j; int visited[maxN] = { 0 }; // 表示顶点是否被选中,0:顶点未被选中;1:顶点已被选中 int last_visited = 0; for (i = 0; i < N; ++i){ out[i] = INF; // 把输出结果全部初始化为无穷大 } visited[v0] = 1; // 选中起始顶点 out[v0] = 0; for (i = 0; i < N - 1; ++i) { // N 个顶点需要做 N - 1 次循环 // 查看顶点周围的所有点 for (j = 0; j < N; ++j) { // 循环遍历所有顶点 if (visited[j] == 0) { // 保证被查看的新顶点没有被访问到 if (matrix[v0][j] != 0){ // 保证当前顶点(V0)与新顶点(j)之间有路径 int dist = matrix[v0][j] + last_visited; // 计算 V0 到 J 的路径距离 if (dist < out[j])out[j] = dist; // 用新路径代替原来的路径 } } } // 找出最小值 int minIndex = 0; while (visited[minIndex] == 1) minIndex++; // 找第一个没有被选中的节点 for (j = minIndex; j < N; ++j) { if (visited[j] == 0 && out[j] < out[minIndex]){ minIndex = j; } } last_visited = out[minIndex]; // 更新最小值 visited[minIndex] = 1; // 将最小值顶点选中 v0 = minIndex; // 下次查找从最限制顶点开始 } } int _tmain(int argc, _TCHAR* argv[]) { #if 0 freopen("Dijkstra2Data.txt", "r", stdin); int result[maxN]; int N, i, j; scanf("%d", &N); for (i = 0; i < N; ++i){ for (j = 0; j < N; ++j){ scanf("%d", &matrix[i][j]); } } Dijkstra_c(result, N, 0); for (i = 0; i < N; ++i){ if (result[i] == INF)printf("INF\n"); else printf("%d\n", result[i]); } #endif freopen("Dijkstra2Data.txt", "r", stdin); int n; scanf("%d", &n); vector<vector<int>> vec(n, vector<int>(n, 0)); for (int i = 0; i < n; ++i){ for (int j = 0; j < n; ++j){ cin >> vec[i][j]; } } vector<int> result(n, INF); // 把输出结果全部初始化为无穷大 Dijkstra_cpp(vec,result, 0); for (int i = 0; i < n; ++i){ if (result[i] == INF)printf("INF\n"); else printf("%d\n", result[i]); } return 0; }
假设我们的测试用例如下图所示:
我们以A作为起始顶点,计算A到每个顶点的最短路径,注意,这是一幅带权图,图的邻接矩阵表示如下:
计算结果如下:
相关文章推荐
- Dijkstra 算法的 C++ 实现
- 迪杰斯特拉(Dijkstra)算法--(C++实现)
- C++实现迪杰斯特拉(Dijkstra)算法
- 单源最短路 Dijkstra 算法 C++高效实现
- Dijkstra 最短路径算法 图示与实现
- C++实现的农历算法
- 算法之二分查找(c++版实现+测试)
- 数据挖掘分类算法之贝叶斯分类法原理及C++实现
- 每对顶点间的最短路径算法时间复杂度改进C++实现
- 算法学习 - 堆排序 ( HeapSort ) C++实现
- C/C++:各种基本算法实现小结(二)—— 堆 栈
- 数据结构:最短路径(Dijkstra c++实现)
- C++ 实现决策树 ID3 算法
- 算法(C++实现)
- 金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 【C++实现有序子序列合并算法】
- 数据结构与算法之递归算法 C++和PHP实现
- C++带赖子的麻将听牌检测算法实现
- 【算法和数据结构】排序(四)归并排序和快速排序(C++实现)
- 快速选择算法 C++实现