图论最短路径算法之Dijkstra算法

这个算法是一种单源最短路径算法,即这个算法只能求出一个点到其他点之间的最短路径,而且这个算法不能处理负边权的图。

算法思路:我们先初始化存图的邻接矩阵,如果我们要求S点到T点的最短距离,我们先初始dis[T](dis[T]表示S点到T点的距离),我们还可以借助一个辅助数组col[]来对这个dis[]进行标记,当col[T]为1时,说明S点到T点的最短距离已经找到。这里我们借助枚举量来对辅助数组进行初始化。

enum Color{Blue,White};//Blue表示是蓝点,需要我们进行检测,White表示不用检测

然后对dis[]数组进行初始化,先将该数组的所有值变为正无穷(dis[S]=0->自己到自己的距离,并将这个下标为S的点染色成白色),表示两点不可达,然后与邻接矩阵配合使用,然后在dis[]数组里找一个下标V使得dis[V]为最小,V标记为白色,在邻接矩阵中查看与V相连的点与V的距离,如果dis[T]>dis[V]+graph[V][T],这个表达式表达S点到T的距离大于S点到V点的距离加上V点到T点的距离,那么将更新dis[]数组为dis[T]=dis[V]+graph[V][T]。然后再进行循环,继续检测dis[]数组里未染成白色的点。

算法步骤:

1.dis[S]=0,col[S]=Color::Blue;

2.dis[!S]=+∞(初始化下标不为S的点为正无穷)

3.for(int i=1;i<=N;i++){//N为点的个数

    if(dis[T]>dis[V]+graph[V][T])dis[T]=dis[V]+graph[V][T];

}

4.算法结束,dis[T]表示从S点T点的最短距离

Dijktrea.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
enum Color{Blue,White};
void Dijkstra(int dis[], int col[], int** graph,int s,int len) {//s为源点,len点的个数
	dis[s] = 0;//源点到源点的距离为0,
	while (true) {
		int minV = -1;//标记最短距离的下标
		int max = 0x3f3f3f3f;
		for (int i = 0; i < len; i++) {
			if (col[i] == Color::Blue && dis[i] < max) {//从蓝色点的中找最小值
				minV = i;
				max = dis[i];
			}
		}
		if (minV == -1)break;//说明所有的点都已经找到最短路径
		col[minV] = Color::White;//标记说明这个点已经找到最小值
		for (int i = 0; i < len; i++) {
			if (dis[i] > dis[minV] + graph[minV][i]) {
				dis[i] = dis[minV] + graph[minV][i];
			}
		}
	}
}
int main() {
	int V_num;
	cout << "please input V number:";
	cin >> V_num;
	int** graph = new int*[V_num];//动态定义二维数组,先申请int*类型的一维指针
	for (int i = 0; i < V_num; i++) {
		graph[i] = new int[V_num];//再给申请的一维指针分配int类型空间
	}
	//邻接矩阵的初始化
	for (int i = 0; i < V_num; i++) {
		for (int j = 0; j < V_num; j++) {
			if (i == j) {
				graph[i][j] = 0;
			}
			else {
				graph[i][j] = 0x3f3f3f3f;//表示两点之间不可达
                graph[j][i] = graph[i][j];说明是无向图
			}
		}
	}
	cout << "graph init success!!!" << endl;
	int E_num;
	cout << "please input E number:";
	cin >> E_num;
	cout << "please input E1andE2 and E1toE2_num:" << endl;;//点与点之间的连接关系
	for (int i= 0; i < E_num; i++) {
		int E1, E2, E1toE2_num;
		cin >> E1 >> E2 >> E1toE2_num;
		E1 -= 1;
		E2 -= 1;
		graph[E1][E2] = E1toE2_num;//邻接矩阵存放点与点之间的联通关系与距离
		graph[E2][E1] = E1toE2_num;
	}
	int* dis =new int[V_num];
	for (int i = 0; i < V_num; i++) {//源点到目标点数组的初始化
		dis[i] = 0x3f3f3f3f;
	}
	int* col = new int[V_num];
	for (int i = 0; i < V_num; i++) {
		col[i] = Color::Blue;//初始化辅助数组,蓝点表示最短路径未求出
	}
	int s, t;
	cout << "please input S and T:";
	cin >> s >> t;
	Dijkstra(dis, col, graph, s - 1, V_num);
	cout << "S to T min distance:";
	cout << dis[t - 1] << endl;
	return 0;
}
/*
测试样例
3->三个点
3->点与点之间的连通关系和距离
1 2 5
2 3 5
3 1 2
1 2->第一个点到第二个点的距离

*/

时间复杂度:O(N^2)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值