最短路径之弗洛伊德算法

一、问题描述

针对无向网图G,求的该图G上任意两个顶点之间的最短路径和最短距离。以下图为例。
无向图G

二、算法过程分析

1、算法复杂度O(n3)

2、 辅助定义

矩阵D : ShortPathTable 用于存储顶点两两之间的距离
矩阵PPathmatrix 用于存储最短路径(即下一个点)
更新公式 :表示从顶点v到顶点w的最短距离为其本身或经过顶点 0 后两段距离之和: D 0 [ v ] [ w ] = m i n { D − 1 [ v ] [ w ] , D − 1 [ v ] [ 0 ] + D − 1 [ 0 ] [ w ] } D^{0}[v][w] = min{ \{ D^{-1}[v][w], D^{-1}[v][0]+D^{-1}[0][w] \}} D0[v][w]=min{D1[v][w],D1[v][0]+D1[0][w]}

3、代码

typedef int Pathmatrix[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];

void ShortestPath_Floyd(Mgraph G,Pathmatrix *P, ShortPathTable *D){
	int v,w,k;
	for(v=0; v<G.numVertexes; ++v){
		for(w=0; w<G.numVertexes; ++w){
			(*D)[v][w] = G.matrix[v][w];//初始化D为最初的邻接矩阵
			(*P)[v][w] = w; //初始化P,使其等于目标点的顶点编号,感性的理解为从顶点v到
							//顶点w,那么路径的下一个点就是目标点w
		}
	}
	//针对每个中转点k,判断起始点v开始到目标点w之间
	for(k=0;k<G.numVertexes;++k){//k为中转点
		for(v=0;v<G.numVertexes;++v){//v为起始点
			for(w=0;w<G.numVertexes;++w){//w为目标点
				//如果经过中转点k后能够使得从v到w的路径变短,则更新路径
				if((*D)[v][w] > (*D)[v][k]+ (*D)[k][w]){
					(*D)[v][w] = (*D)[v][k] + (*D)[k][w];	
					(*P)[v][w] = (*P)[v][k];//这里的原因下方详细说明。
											//一个感性的理解是,从v到w要经过k,那么
											//我需要获得从v到k应该走的下一个结点是谁
				}
			}
		}
	}
}

** D0 就是邻接矩阵**在这里插入图片描述 P0: P[v][w]=w
在这里插入图片描述

** D1:从v0到v8,依次判断经过中间点v1后是否路径更短,若更短,则更改路径长度为经过中间点v1后的:即D[v][w] = D[v][v1]+D[v1][w]**
在这里插入图片描述
P1:P1的更改对应D1的更改,由于经过v1后距离更短,所以P1的对应位置应修改为P[v][1] = 1.
这里很好理解,因为经过的是结点v1,所以修改P矩阵中对应项为1,且此时由于P[v][1]=1,所以修改为P[v][1]或是1均可。
在这里插入图片描述

经过v1点修改P为P[v][1]没有问题,但是由于我之前理解的偏差,认为经过哪个点,就应该修改对应的P为那个点的坐标 应该P[v][w]=k吧?我这样想到,最开始P[v][k] = k还可以理解两者是一样的,但当修改过一次P矩阵后,P[v][k] = k就不成立了,代码为何还要这么写呢?是不是有问题呢?

其实这是我理解的错误,我们通过D2和P2的变化来说明

在这里插入图片描述

注意:此时绿色部分是经过中转点v2后,可以得到更短路径的更新部分
注意到从v0v4原路径长度为6,由于v0经过v2(长度为4)再到v4(长度为1),得到总长度为5<6,因此更新D[0][4]为5此时你是不是想将P[0][4]更新为2?(因为这条路径经过顶点2了,所以应该更新)

如果你这么想,就错了。

注意到: 最初当 D[0][4] =6时 ,P[0][4]=1, 说明此时从顶点v0顶点v4,是需要经过顶点v1的,P矩阵表示的是从某个顶点开始到目标顶点,要走的下一个顶点是谁。 虽然我们发现经过顶点v2可以获得从顶点v0顶点v4的更加段的路径,但不要忘记,这条路径是要先经过顶点v1的。因此P[0][4] 应=P[0][2]=1。

这个时候你可能会想:那我经过v2这个顶点的信息不就丢失了吗?
不要着急,我们接着看从顶点v1到顶点v4。

注意到从v1v4原路径长度为5,由于v1经过v2(长度为3)再到v4(长度为1),得到总长度为4<5,因此更新D[1][4]为4

此时P[1][4] = P[1][2] = 2

其实P[1][4] = P[1][2] = 2在无形中包含了顶点v0到顶点v4需要经过顶点v2的信息
原因很简单:由于顶点v0到顶点v4路径为 v0➡️v1➡️v2➡️v4,所以v0到v4需要经过v2实际上说明v1到v4需要经过v2,所以我们在更新P矩阵时,应保留P[0][4]=P[0][2]=1,表示我们需要先到顶点v1,而修改P[1][4]=P[1][2]=2则表示从顶点v1到顶点v4应该经过一下顶点v2,这样可以获得更短的路径。

不用担心P矩阵的更新会丢失信息,因为我们是对每个顶点都进行更新的。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值