弗洛伊德演算法(每一對頂點之間的最短路徑)

2021-07-03 09:19:03 字數 4620 閱讀 2010

for( int i = 1 ;i <= vtxnum; ++i )

for( int j = 1; j <= vtxnum; ++j)

for( k = 1; k <= vtxnum; ++k) //中間點

for( int i = 1; i <= vtxnum; ++i)

for(int j = 1; j <= vtxnum ; ++j)

if( dist[i][k] + dist[k][j] < dist[i][j])

//dist是兩點間最短距離,cost是邊權值,path是路徑

floyd演算法的基本思想如下:從任意節點a到任意節點b的最短路徑不外乎2種可能,1是直接從a到b,2是從a經過若干個節點x到b。所以,我們假設dis(ab)為節點a到節點b的最短路徑的距離,對於每乙個節點x,我們檢查dis(ax) + dis(xb) < dis(ab)是否成立,如果成立,證明從a到x再到b的路徑比a直接到b的路徑短,我們便設定dis(ab) = dis(ax) + dis(xb),這樣一來,當我們遍歷完所有節點x,dis(ab)中記錄的便是a到b的最短路徑的距離。

很簡單吧,**看起來可能像下面這樣:

for(inti = 0; i < 節點個數; ++i )

}

}

}

但是這裡我們要注意迴圈的巢狀順序,如果把檢查所有節點x放在最內層,那麼結果將是不正確的,為什麼呢?因為這樣便過早的把i到j的最短路徑確定下來了,而當後面存在更短的路徑時,已經不再會更新了。

讓我們來看乙個例子,看下圖:

圖中紅色的數字代表邊的權重。如果我們在最內層檢查所有節點x,那麼對於a->b,我們只能發現一條路徑,就是a->b,路徑距離為9。而這顯然是不正確的,真實的最短路徑是a->d->c->b,路徑距離為6。造成錯誤的原因就是我們把檢查所有節點x放在最內層,造成

過早的把a到b的最短路徑確定下來了,當確定a->b的最短路徑時dis(ac)尚未被計算。所以,我們需要改寫迴圈順序,如下:

for(intk = 0; k < 節點個數; ++k )

}

}

}

這樣一來,對於每乙個節點x,我們都會把所有的i到j處理完畢後才繼續檢查下乙個節點。

那麼接下來的問題就是,我們如何找出最短路徑呢?這裡需要借助乙個輔助陣列path,它是這樣使用的:path(ab)的值如果為p,則表示a節點到b節點的最短路徑是a->...->p->b。這樣一來,假設我們要找a->b的最短路徑,那麼就依次查詢,假設path(ab)的值為p,那麼接著查詢path(ap),假設path(ap)的值為l,那麼接著查詢path(al),假設path(al)的值為a,則查詢結束,最短路徑為a->l->p->b。

那麼,如何填充path的值呢?很簡單,當我們發現dis(ax) + dis(xb) < dis(ab)成立時,就要把最短路徑改為a->...->x->...->b,而此時,path(xb)的值是已知的,所以,path(ab) = path(xb)。

好了,基本的介紹完成了,接下來就是實現的時候了,這裡我們使用圖以及鄰接矩陣:

#define infinite 1000           // 最大值

#define max_vertex_count 20   // 最大頂點個數

//

structgraph

;

//

首先,我們寫乙個方法,用於讀入圖的資料:

voidreadgraphdata( graph *_pgraph )

}

}

接著,就是核心的floyd演算法:

voidfloyd(int_arrdis[max_vertex_count],int_arrpath[max_vertex_count],int_nvertexcount )

}

//

for(intk = 0; k < _nvertexcount; ++k )

}

}

}

}

ok,最後是輸出結果資料**:

voidprintresult(int_arrdis[max_vertex_count],int_arrpath[max_vertex_count],int_nvertexcount )

else

while( k != i );

//

std::cout << stackvertices.top()+1;

stackvertices.pop();

unsignedintnlength = stackvertices.size();

for( unsignedintnindex = 0; nindex < nlength; ++nindex )

std::cout <<" -> "<< j+1 << std::endl;

}

}

}

}

}

好了,是時候測試了,我們用的圖如下:

測試**如下:

intmain(void)

}

floyd( arrdis, arrpath, mygraph.nvertexcount );

//

printresult( arrdis, arrpath, mygraph.nvertexcount );

//

system("pause");

return0;

}

如圖:

弗洛伊德演算法求每一對頂點之間的最短路徑

include define vertex num 3 define infinity 10000 define true 1 define false 0 typedef struct graph graph void shortestpath graph g,int p vertex num v...

弗洛伊德演算法 從某個頂點到其他頂點之間的最短路徑

弗洛伊德演算法 include include include include define infinity 65535 定義乙個無限大的值 define maxsize 50 最大頂點個數 include using namespace std typedef char vertextype 4...

每隊頂點之間的最短路徑(弗洛伊德演算法)

floyd演算法 又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的演算法,與dijkstra演算法類似。該演算法名稱以創始人之一 1978年圖靈獎獲得者 史丹福大學電腦科學系教授羅伯特 弗洛伊德命名。通過乙個圖的權值 矩陣求出它的每兩點間的 最短路徑矩陣。從圖的帶權 鄰接...