Dijkstra算法(迪杰斯特拉算法)
该算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题
迪杰斯特拉算法的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
迪杰斯特拉算法的成功率是最高的,因为它每次必能搜索到最优路径。但迪杰斯特拉算法算法的搜索速度是最慢的。迪杰斯特拉算法求一个点到其他所有点的最短路径时间复杂度为O ( n 2 )
参考博客:Dijkstra算法(迪杰斯特拉算法)_持之以恒2016-CSDN博客_迪杰斯特拉算法
博主将该算法的思路讲的非常透彻,强烈建议细细研读
接下来是我的学习笔记:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号,求城市s到城市d的最短距离(题目来源:pta城市救援,同时我对该题进行简化,方便进行解析)
第一步:准备工作
我们首先要创建一个二维数组来判断两点之间是否存在通路,并将每个点之间的距离初始化为非常大(我用的999,自己用的数据比较小)以及建立一个数组来判断每个点是否被访问。
int vist[100]={0};//判断是否到达,将所有点初始化为0,即未被访问过
int road[100][100];//两城市间是否存在通路
for(int i = 0;i< 100;i ++)
for(int j = 0; j<100;j++)
road[i][j]=999;
int n, m, s, d;
cin>> n>> m>> s>> d;
for(int i = 1; i <= m; i++){//将通路填入数组(通路数值小于初始化值)
int x,y,z;//起始城市x 末尾城市y 通路长度z
cin>>x>>y>>z;
road[x][y] = z;
road[y][x] = z;//x->y与y->x距离长度一样
}
第二步:一次大遍历中我们应该做的操作
我们将出发城市S设置为已访问,然后遍历每一个城市,寻找与之相连的最短路径城市(假设为城市f),然后将其记录下来,方便下次操作。
int f = -1;//用来判断该城市是否还与其他城市相通
minn = 999;
for(int j = 0; j < n; j ++){//遍历与该次临时起点J相连的点
if(vist[j] == 0&&road[s][j] < minn){//若J
minn = road[s][j];
f = j;
}
}
if(f == -1)break;//隐晦的表达每一个点都被访问了,此时是最后一次循环
vist[f] = 1;//将找到的最近城市设置为已访问。
然后我们以找到的最近城市f,再进行一次遍历,找到与f相连的且未被标记过的城市,更新该城市到源头城市S的距离。
for(int j = 0;j < n; j++){
if(vist[j] == 0 && road[s][f] + road[f][j] < road[s][j]){
road[s][j] = road[s][f] + road[f][j];
}
}
到这,一次遍历后我们已经更新了源头城市S与其他城市的距离
上完整代码
#include <bits/stdc++.h>
using namespace std;
int vist[100]={0};//判断是否到达,将所有点初始化为0,即未被访问过
int road[100][100];//两城市间是否存在通路
int main(){
int n, m, s, d;
cin>> n>> m>> s>> d;
for(int i = 0;i< 100;i ++)
for(int j = 0; j<100;j++)
road[i][j]=999;
for(int i = 1; i <= m; i++){
int x,y,z;
cin>>x>>y>>z;
road[x][y] = z;
road[y][x] = z;
}
vist[s] = 1;
int minn = 999;
//cout<<lj[0][2]<<endl;
// dijkstra算法实现 可以将其定义在主函数外
for(int i = 0; i < n; i ++){//最实在的方式遍历七次
int f = -1;//用来判断该城市是否还与其他城市相通
minn = 999;
for(int j = 0; j < n; j ++){//遍历与该次临时起点J相连的点
if(vist[j] == 0&&road[s][j] < minn){//若J
minn = road[s][j];
f = j;
}
}
if(f == -1)break;//隐晦的表达每一个点都被访问了,此时是最后一次循环
vist[f] = 1;//将找到的最近城市设置为已访问。
for(int j = 0;j < n; j++){
if(vist[j] == 0 && road[s][f] + road[f][j] < road[s][j]){
road[s][j] = road[s][f] + road[f][j];
}
}
}
cout<<road[s][d];
return 0;
}
附赠一组链接博客的测试组数据方便大家敲完代码去验证,也可以自行画图设计数据去检验自己程序正确性
起始A为0,B为1,以此内推
7 11 0 3
0 1 12
0 5 16
0 6 14
1 2 10
1 5 7
2 3 3
2 5 6
2 4 5
3 4 4
4 5 2
4 6 8
最后,感谢Dijkstra算法(迪杰斯特拉算法)_持之以恒2016-CSDN博客_迪杰斯特拉算法
该文章让我非常清楚的了解迪杰斯特拉算法的原理。
最后感谢大家的阅读,希望能够帮助大家理解该算法的代码实现过程。
收工over!