最短路径(Floyd算法,弗洛伊德算法,多源最短路径)

算法思想:一开始各顶点之间的最短路径,就是邻接矩阵值,每一次加入一个顶点,然后判断该顶点加入后,其余起点通过该顶点到达其余顶点能否得到比之前更短的最短路径,如果找到了就进行最短路径和权值和的更新
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法伪代码

在这里插入图片描述

代码实现和相关代码注释

#include<iostream>
using namespace std;
#define Max 10//最大顶点数
#define MANY 65535
class Graph
{
    
    
private:
	int verNum;//顶点个数
	int arcNum;//边的个数
public:
	int ver[Max];//顶点数组
	int arc[Max][Max];//网图的邻接矩阵
public:
	Graph(int v[], int n, int e);
	int getVernum()
	{
    
    
		return verNum;
	}
	int getArcnum()
	{
    
    
		return arcNum;
	}

};
Graph::Graph(int v[], int n, int e)
{
    
    
	verNum = n;
	arcNum = e;
	for (int i = 0; i < verNum; i++)
		ver[i] = v[i];
	for (int i = 0; i < verNum; i++)
	{
    
    
		for (int j = 0; j < verNum; j++)
		{
    
    
			if (i == j)
			{
    
    
				arc[i][j] = 0;
			}
			else {
    
    
				arc[i][j] = MANY;
			}
		}
	}
	cout << "请输入每条边依附的两个顶点和权值:" << endl;
	int vi = 0, vj = 0, k = 0;
	for (int i = 0; i < arcNum/2; i++)
	{
    
    
		cin >> vi >> vj >> k;
		arc[vi][vj] = k;
		arc[vj][vi] = k;
	}
}
//佛洛伊德算法:最短路径P数组  最短路径长度d数组
void Shorttestpath_Floyd(Graph G, int(*p)[Max], int(*d)[Max])
{
    
    
	//初始化最短路径数组p和最短路径长度数组d
	for (int i = 0; i < G.getVernum(); i++)
	{
    
    
		for (int j = 0;j < G.getVernum(); j++)
		{
    
    
			//最短路径长度一开始就是邻接矩阵中记录各顶点不通过其他顶点所能到达其他顶点的距离
			d[i][j] = G.arc[i][j];
			//初始化时:0---1的最短路径就是0---1,0---2的最短路径就是0----2
			p[i][j]=j;
		}
	}
	//外层循环,每一次加入一个新顶点,例如:先加入v0看是否产生最优解,再挨个加入剩余顶点,每一次都查看是否产生最优解
	for (int i = 0; i < G.getVernum(); i++)
	{
    
    
		//两重内层循环遍历最短路径长度的数组
		for (int j = 0; j < G.getVernum(); j++)
		{
    
    
			for (int k = 0; k < G.getVernum(); k++)
			{
    
    
				//例如初始时d[0][2]=1表示0-->2的最短距离为1,加入第二个节点1后,此时d[0][1]+d[1][2]=7
				//表示0---1----2的距离为7,比当前存储的最短路径长度长,因此不做更新
				if (d[j][k] > d[j][i] + d[i][k])
				{
    
    
					//满足条件就更新
					d[j][k] = d[j][i] + d[i][k];
					//如果加入节点1后,0---1---2的距离为2,而没有加入前最短距离为7,那么此时更新最短路径
					//把之前p[0][2]=2,表示通过0可以直接到达2,不需要经过其他顶点
					//把p[0][2]=p[0][1]=1,从而去查找p[1][2]查看1--->2是否还需要经过其他顶点
					//表示0---2需要经过顶点1,但是我们在最后输出最短路径的时候,还需要去寻找1--->2是否还需要经过其他顶点
					p[j][k] = p[j][i];
				}
			 }
		}
	}
}
//打印最短路径
void display(Graph g, int(*p)[Max],int(*d)[Max])
{
    
    
	//外层循环是每次循环求出一个顶点的最短路径
	for (int i = 0; i < g.getVernum(); i++)
	{
    
    
	      //内存循环负责求出当前顶点的最短路径
		//p[i][j]是为了求出当前顶点i到剩余出i之外的顶点的最短路径
		for (int j = i+1; j < g.getVernum(); j++)
		{
    
    
			cout << i << "->" << j << "的最短路径长度:" << d[i][j] << endl;
			cout << "最短路径:";
			int k = p[i][j];//获得第一个路径顶点的下标
			//打印当前最短路径的起点
			cout << i;
			//如果打印的不是终点
			while (k != j)
			{
    
    
				//打印起点到达终点的过程中所有经过的顶点
				cout << "->" << k;
				k = p[k][j];//获得下一个路径顶点的下标
			}
			//打印终点j
			cout << "->" << j << endl;
		}
	}
}
//测试----------------------
void test()
{
    
    
	int v[3] = {
    
     0,1,2 };//顶点数组
	Graph g(v, 3, 6);//3个顶点连通网图
	cout << "打印邻接矩阵" << endl;
	for (int i = 0; i < g.getVernum(); i++)
	{
    
    
		for (int j = 0; j < g.getVernum(); j++)
		{
    
    
			cout << g.arc[i][j]<<"\t";
		}
		cout << endl;
	}
	//最短路径数组
	int minPath[Max][Max] = {
    
     0 };
	//最短路径长度数组
	int minLen[Max][Max] = {
    
     0 };
	Shorttestpath_Floyd(g, minPath, minLen);
	cout << "打印最短路径" << endl;
	display(g, minPath, minLen);
}
int main()
{
    
    
	test();
	system("pause");
	return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_53157173/article/details/115255509