1. 程式人生 > >最短路徑演算法—Floyd(弗洛伊德)演算法

最短路徑演算法—Floyd(弗洛伊德)演算法

Floyd演算法(解決任意兩點間的最短路徑,可以正確處理有向圖或負權值的最短路徑問題):

時間複雜度O(N3),空間複雜度O(N2);

演算法思想:

Floyd演算法是一個經典的動態規劃演算法;首先我們的目標是計算頂點i到j的最短路徑,從動態規劃角度來看:

從節點i到節點j的最短路徑不外乎兩種可能:1)直接從i到j; 2) i經過若干節點再到j;所以我們可以這樣來計算i j之間的最短距離:對於每一個結點k,我們判斷Dist(i,k)+Dist(k,j)<Dist(i,j)是否成立,如果成立,則證明從i到k,再從k到j的距離比直接從i到j的距離短,所以我們更新Dist(i,j)=Dist(i,k)+Dist(k,j); 這樣,遍歷完所有的k值,則得到最終從i到j的最小距離。

Floyd演算法過程:

1、用D[i][j]記錄每兩個頂點之間的距離;

2、依次掃描每一個頂點k,以該點為基準,判斷從i經過k,再到j的距離是否小於D[i][j],若是則更新D[i][j]=D[i][k]+D[k][j];

精髓:依次掃描每一點(k),並以該點作為中介點,計算出通過k點的其他任意兩點(i,j)的最短距離,這就是floyd演算法的精髓!同時也解釋了為什麼k點這個中介點要放在最外層迴圈的原因.

typedef struct
{
	char vertex[MAXVER];
	int edges[MAXVER][MAXVER];
	int n, e;
}MGraph;
void Floyd(MGraph g)
{
	int D[MAXVER][MAXVER];
	int path[MAXVER][MAXVER];
	int n = g.n;
	for (int i = 0; i < n; ++i) //初始化
	{
		for (int j = 0; j < n; ++j)
		{
			D[i][j] = g.edges[i][j];
			path[i][j] = -1;
		}
	}
	for (int k = 0; k < n; k++) //注意:一定要理解為什麼把k放在最外層的迴圈,而不放在最內層!!
	{
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				if (D[i][j]>D[i][k] + D[k][j])
				{
					D[i][j] = D[i][k] + D[k][j];
					path[i][j] = k;
				}
			}
		}
	}
}