Dijkstra算法(迪杰斯特拉算法)

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!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值