Floyd算法的原理和实现

一.算法介绍

Floyd算法是一种在有向图中求最短路径的算法。相比不能再有向图中包含负权值的dijkstra算法,Floyd算法可以用在拥有负权值的有向图中求解最短路径(不过不能包含负权回路)。它是一种求解有向图中点与点之间最短路径的算法。

我们检查有向图中的每一个节点X,对于图中过的2点A和B,如果有Dis(AX)+Dis(XB)

所以,核心代码很简单,其中N是顶点个数,时间复杂度为O(N^3)

其中要注意3个for循环的嵌套顺序

void floyd(int N)
{
	int i,j,k;
	for(k=0;k
二.算法的原理

Floyd算法原理是一种动态规划的思想。

Ak(i,j)表示从i点到j点索引号不大于K的最短路径,

则求出最短路径,可表示为

for(K=0;K

然后依次求A0(i,j), A1(i,j), ..., An(i,j) ,其中A0(i,j)表示初始化时候的图

在这个过程中,我们要先求A0(i,j)才能求A1(i,j),再求A2(i,j).....所以这是一种自底向上的设计思想,为什么要先求A0(i,j)才能求A1(i,j),再求A2(i,j)呢.....

因为算法的运行过程是这样的。

我们可以由Ak(i,j)求出Ak-1(i,j),那么对于Ak(i,j)来说,无外乎2种情况

第一种:

Ak(i,j)不经过点k,此时

Ak(i,j)=Ak-1(i,j)

因为对于索引号不经过k的2个点i,j,竟然经过k了,那么就应该在索引号不大于K-1里面找最短路径了

第二种:

Ak(i,j)经过了点k,此时

Ak(i,j)=Ak-1(i,k)+Ak-1(i,k)

因为经过了k,所以此时路径分2部分,一部分是从i到k,另外一部分是k,到j,因为k此时已经作为了2部分路径的起点或者终点,所以此时要求这2部分的最短路径时,就是使用Ak-1(i,k)和Ak-1(i,k)。这是一种DP的思想。

那么2种情况我最后肯定是选路径断的那一条,

所以Ak(i,j) = min( Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j) )

这一步其实就对应了代码部分的:

if(Dis[i][k]+Dis[k][j]
三:打印路径

用path[i][j]纪录路径信息。

假设我们存在路径1→5→7→9,那么先求path[1][9]=7,再求path[1][7]=5,再求path[1][5]=1。

所以,算法应该改为,其中加入path[i][j]=k,因为当路径更新,该路径进过了k点,所以要纪录下来

void floyd(int N)
{
	int i,j,k;
	for(k=0;k
path[i][j]初始化代码:

一开始我们假设图的任意2点都是连接的

	for(i=0;i
四:源码
该代码用邻接矩阵存储图,输入1000表示2个顶点不可达(权值无限大)

#include
#include
using namespace std;
#define MAX 1000
int Graph[MAX][MAX];
int Dis[MAX][MAX];
#define infinite 1000
int path[MAX][MAX];

void floyd(int N)
{
	int i,j,k;
	for(k=0;k ph;
				do
				{
					k=path[i][k];
					ph.push(k);
				}while(k!=i);
				cout<"<"<>N;
	for(i=0;i>g;
			Graph[i][j]=g;
			Dis[i][j]=g;
		}
	}
//初始化路径
		for(i=0;i

测试用的图:

Floyd算法的原理和实现_第1张图片

测试结果:

Floyd算法的原理和实现_第2张图片



你可能感兴趣的:(最短路径算法大全)