狄克斯特拉算法(Dijkstra)
问题背景与定义
构建邻接矩阵
构建最短距离上界的估计值数组
问题求解过程
1号顶点所有出边进行松弛
2号顶点所有出边进行松弛
4号顶点所有出边进行松弛
3号顶点所有出边进行松弛
5号顶点所有出边进行松弛
6号顶点所有出边进行松弛
总结:每次从所有没有进行选择的点中选择“估计值”最小的点,通过该点的所有出边对相连的点进行松弛操作,依次循环,直到所有顶点被选完为止。
主要过程:1、选点 2、出边松弛dis 3、1-2循环过程为n-1次(n为点的个数,最后一个点不再需要进行松弛操作)
问题程序实现
#include <bits/stdc++.h>
using namespace std;
//邻接矩阵方式存储
int f = 9999;
//图的顶点数量与边数
int n = 6, m = 9;
int main() {
//初始化
//初始化邻接矩阵
int e[6][6] = {
{0, 1, 12, f, f, f},
{f, 0, 9, 3, f, f},
{f, f, 0, f, 5, f},
{f, f, 4, 0, 13, 15},
{f, f, f, f, 0, 4},
{f, f, f, f, f, 0}
};
//初始化dis数组
int dis[6] = {0, f, f, f, f, f};
//初始化book数组
int book[6] = {0};
int min_index = 0;
int min_dis = f;
//实现过程 总的循环过程 寻找n-1个点
for (int i = 0; i < n - 1; i++) {
//找点 次数寻找
min_dis = f;
for (int j = 0; j < n; j++) {
if (book[j] == 0 && dis[j] < min_dis) {
min_dis = dis[j];
min_index = j;
}
}
//标记点
book[min_index] = 1;
//找出边进行松弛操作
for (int j = 0; j < n; j++) {
if (e[min_index][j] < f && book[j] == 0) { //出边 且 没有找过该点
dis[j] = min(dis[j], dis[min_index] + e[min_index][j]); //松弛操作
}
}
//打印松弛过程
for (int d = 0; d < n; d++) {
cout << dis[d] << " ";
}
cout<<endl;
}
return 0;
}
注意事项:
(1) Dijkstra算法无法解决带有负权边的图(在该算法每步松弛过程后认为找到的最短估计值已经是最短距离,如果后续还有点可以通过负边到达原来的点,使原来的点距离变得更短,那么后面做的工作就是不正确的了)。
(2) Dijkstra算法的时间复杂度为O(n^2),主要解决单源最短距离问题(由源点都任意一点之间的最短距离)。
(3) Dijkstra算法是使用明确边对最短路进行松弛操作,当边的数量远大于点的数量时,该算法可以实现较好的效果。