最短路径_Floyd算法(多源)

Floyd算法是一个经典的动态规划算法,它又被称为插点法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。Floyd算法是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,算法目标是寻找从点i到点j的最短路径。
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,算法假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,算法检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

Floyd算法内容

在这里插入图片描述
//求每队顶点之间的最短路径
//实现这个目的,有2种方式:
//1.利用每个顶点为源头,共调用n次Dijstra算法
//2.Floyd算法,上下方案都是o(n^3)
//辅助结构 1.二维数组Path[i][j],记录前驱
// 2.二维数组D[i][j],记录最短路径长度

//具体步骤:
//初始化:D[i][j]=G.ver[i][j],然后进行(n-1)次比较和更新
//1.在vi和vj之间加入顶点v0,比较(vi,vj)和(vi,v0,vj)的路径长度,取其中最短的作为vi到vj的最短路径
//2.在vi和vj之间加入v1,得到(vi,……,v1)和(v1,……,vj),其中前者是vi到v1且中间顶点序号不大于0的最短路径
//			后者是v1到vj且中间顶点序号不大于0的最短路径,取其中较短者作为vi到vj的最短路径
//依次类推,重复n次比较
#include<iostream>
#define MaxInt 32767//无穷大
#define MaxNum 10
using namespace std;


typedef char VerType;//数据类型
typedef int ArcType;//权值类型
typedef struct {
	VerType ver[MaxNum];//顶点表
	ArcType arc[MaxNum][MaxNum];
	int vernum, arcnum;//点数,边数
}AMGraph;
//定位
int Locate(AMGraph G, VerType v1) {
	for (int i = 0; i < G.vernum; i++) {
		if (G.ver[i] == v1) {
			return i;
		}
	}
	return -1;
}
//创建
bool createUDN(AMGraph&G) {
	cout << "Please input the vernum and arcnum" << endl;
	cin >> G.vernum >> G.arcnum;
	int i, j, p, q;
	cout << "Please input the  name of points" << endl;
	for ( i = 0; i < G.vernum; i++) {
		cin >> G.ver[i];
	}
	//初始化
	for (i = 0; i < G.vernum; i++) {
		for (j = 0; j < G.vernum; j++) {
			if (i != j)
				G.arc[i][j] = MaxInt;
			else
				G.arc[i][j] = 0;
		}
	}
	VerType v1, v2;
	ArcType w;
	cout << "Please input arcnum graph" << endl;
	for (i = 0; i < G.arcnum; i++) {
		cin >> v1 >> v2 >> w;
		p = Locate(G, v1);
		q = Locate(G, v2);
		G.arc[p][q] = w;
		G.arc[q][p] = G.arc[p][q];
	}
	return true;
}
void show(AMGraph G) {
	int i, j;
	for (i = 0; i < G.vernum; i++) {
		for (j = 0; j < G.vernum; j++) {
			if (G.arc[i][j] == MaxInt)  printf("INF\t");
			else 
				printf("%-3d\t", G.arc[i][j]);
		}
		cout << endl;
	}
}
void show(AMGraph G, int ** D,int **path,int length,int i,int j) {
	if (path[i][j] == i) {
		cout << G.ver[path[i][j]] << " ";
		return;
	}
	else {
		show(G, D, path, length, i,path[i][j]);
		cout << G.ver[path[i][j]] << " ";
	}
}
void smallPath_Floyd(AMGraph G) {
	int n = G.vernum;
	int ** path = new int *[n];
	int **D = new int *[n];
	for (int j = 0; j < n; j++) {
		path[j] = (int *)calloc(G.vernum, sizeof(VerType)*G.vernum);//申请全为空的空间
	}
	for (int i = 0; i < n; i++) {
		 D[i] = (int *)calloc(G.vernum, sizeof(VerType)*G.vernum);//申请全为空的空间
	}
	//初始化path和D[][]
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			D[i][j] = G.arc[i][j];
			if (D[i][j] < MaxInt && i != j)
				path[i][j] = i;
			else 
				path[i][j] = -1;
		}
	}
	//开始比较
	for (int i = 0; i < n; i++) {//i是第三者,插足于j到k
		for (int j = 0; j < n; j++) {
			for (int k = 0; k < n; k++) {
				if (D[j][i] + D[i][k] < D[j][k]) {
					D[j][k] = D[j][i] + D[i][k];
					path[j][k] = path[i][k];//更改k的前驱为i
				}
			}
		}
	}
	cout << "每个点的前驱" << endl;
	for (int i = 0; i < n; i++) {
		cout << "第" << i << "行" << " ";
		for (int j = 0; j < n; j++) {
			cout << path[i][j] << " ";
		}
		cout << endl;
	}
	cout << "点i\j的距离" << endl;
	for (int i = 0; i < n; i++) {
		cout << "第" << i << "行" << " ";
		for (int j = 0; j < n; j++) {
			cout << D[i][j] << " ";
		}
		cout << endl;
	}
	//查找过程,举例:(3,0)->(3,1)->(3,2)->(3,3)意思是3要到0,必须走的路是3->2->1->0
	for (int i= 0; i < n; i++) {
		for (int j = 0; j < n; j++) {//n*n的路径全部展示
			if ( D[i][j] >= MaxInt)
				cout << "结点" << G.ver[i] << "到结点" << G.ver[j] << "没有路径可以走" << endl;
			else if (D[i][j] != 0 && D[i][j] < MaxInt) {
				cout << "结点" << G.ver[i] << "到结点" << G.ver[j] << "路径最小长度" << D[i][j] <<"  ";
				cout << "路径为" << "\t";
				show(G, D, path, n, i, j);
				cout << G.ver[j] << "\n\n";
			}
		}
	}
	delete[]path;
	path = NULL;
	delete[]D;
	D = NULL;
}
int main() {
	AMGraph G;
	createUDN(G);
	show(G);
	smallPath_Floyd(G);
}

/*测试案例1:
7 9
0 1 2 3 4 5 6
0 1 28
0 5 10
1 2 16
1 6 14
5 4 25
4 6 24
4 3 22
2 3 12
3 6 18
*/

/*测试案例2:
7 9
a b c d e f g
a b 28
a f 10
b c 16
b g 14
f e 25
e g 24
e d 22
c d 12
d g 18
*/
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
来自百度百科解释https://www.baidu.com/link?url=LtedLFS8klJBnfM_5T2EDw1FF3Np2sDW7ByvjRGGtrD6mWaxSLpLITM7_XgkXdL15nvlz4FNDZupTQATwCRNGrGPT0yX2rbhQ1NPnEXOhWi&wd=&eqid=bfa6b1b0001728fb000000065e0455d8

发布了122 篇原创文章 · 获赞 14 · 访问量 6196

猜你喜欢

转载自blog.csdn.net/weixin_44001521/article/details/103715198
今日推荐