2的传送门https://blog.csdn.net/qq_45839708/article/details/104395614
1.迪杰斯特拉(Dijkstra)算法
我们结合图片与代码讲解:
如上图求最短路径…
有没有人跟我一样第一反应就是用最笨的方法一条路一条路的计算。
很明显这样子是非常浪费时间的,而且运算量对我带说很大。
迪杰斯特拉算法拯救了我(虽然一开始看得非常头大)
迪杰斯特拉算法其核心是:走一步看一步,一步一步的来(31~38行),从而得到最短路径;也实现了源点到所有点的最短路径。
1.const int INF = 1e6;
2.const int N = 1e3;
3.
4.void dijkstra(int n, int mp[N][N], p[N], s[N]) // n代表顶点个数;mp 代表存储着所有点到所有点的邻接矩阵
5.{ // p 存储着该下标位置的前缀(如p[1] = 0 即为0 -> 1)
6. // s 为 shortes_path 简写,代表源点到所有点的最短距离
7. int i, j, k, min;
8. int judge[N] = {0}; // 判断该下标位置是否已存在最短路径
9.
10. for(i = 0; i < n; i++)
11. {
12. s[i] = mp[0][i]; // 初始化最短距离为源点到该点的直接路径长度
13. p[i] = 0; // 初始化各点前缀为源点
14. }
15.
16. s[0] = 0; // 0到0距离为0
17. judge[0] = 1; // 0到0已经有最短距离
18.
19. for(i = 1; i < n; i++)
20. {
21. min = INF;
22. for(j = 1; j < n; j++)
23. {
24. if(!judge[j] && s[j] < min) //寻找此时与源点距离最小的点
25. {
26. min = s[j];
27. k = j;
28. }
29. }
30. judge[k] = 1; //将此点标记为已拥有最短路径
31. for(j = 1; j < n; j++)
32. { // 此处印证了走一步看一步思想,我们可以以此得到:
33. if(min + mp[k][j] < s[j]) //与此时与源点最短距离点 *相邻的点* **当前** 的最短路径
34. { //(注意是当前的最短距离,不一定是最终的)
35. s[j] = min + mp[k][j];
36. p[j] = k; //此时 k 与源点距离最短,则与 k 相邻的点的前缀为 k
37. }
38. }
39. }
40.}
我们来模拟一下代码:
p 初始化后:{ 0,0,0,0,0,0,0,0,0 };
s 初始化后:{ INF,1,5,INF,INF,INF,INF,INF,INF};-> { 0,1,5,INF,INF,INF,INF,INF,INF };//经过第16行后
judge 初始化后:{ 0,0,0,0,0,0,0,0,0 };-> { 1,0,0,0,0,0,0,0,0 };//经过第17行后
进入第19行
找到第一个 min = s[ 1 ] = 1; k = 1;
如图:
更新 p , s, judge
p { 0,0,0,0,0,0,0,0,0 };-> { 0,0,1,1,1,0,0,0,0 };
s { 0,1,5,INF,INF,INF,INF,INF,INF }; -> { 0,1,4,8,6,INF,INF,INF,INF };
judge { 1,0,0,0,0,0,0,0,0 };-> { 1,1,0,0,0,0,0,0,0 };
接下来第二次
如图:
…持续更新 p , s, judge;
最终求得 s 到所有点的最短距离(路径)