floyd
演算法floyd演算法又稱為
弗洛伊德演算法
,插點法,是一種用於尋找給定的
加權圖中頂點間
最短路徑
的演算法。該
演算法名稱以創始人之一、2023年圖靈獎獲得者、史丹福大學電腦科學系教授
羅伯特·弗洛伊德
命名。正如我們所知道的,floyd演算法用於求最短路徑。floyd演算法可以說是warshall演算法的擴充套件,三個for迴圈就可以解決問題,所以它的時間複雜度為o(n^3)。
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 ( int i = 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 ( int k = 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)。(path(xb) = y. 其中 x->... ->y->b 所得的y也是path(ab) 的值 a->...->x->...->y->b)
好了,基本的介紹完成了,接下來就是實現的時候了,這裡我們使用圖以及鄰接矩陣:
#define infinite 1000 // 最大值
#define max_vertex_count 20 // 最大頂點個數//
struct graph
;//
首先,我們寫乙個方法,用於讀入圖的資料:
void readgraphdata( graph *_pgraph )}}
接著,就是核心的floyd演算法:
void floyd( int _arrdis[max_vertex_count], int _arrpath[max_vertex_count], int _nvertexcount )}//
for ( int k = 0; k < _nvertexcount; ++k )}}
}}
ok,最後是輸出結果資料**:
void printresult( int _arrdis[max_vertex_count], int _arrpath[max_vertex_count], int _nvertexcount )
else
while ( k != i );
//std::cout << stackvertices.top()+1;
stackvertices.pop();
unsigned int nlength = stackvertices.size();
for ( unsigned int nindex = 0; nindex < nlength; ++nindex )
std::cout << " -> " << j+1 << std::endl;}}}}}
好了,是時候測試了,我們用的圖如下:
測試**如下:
int main( void )
}floyd( arrdis, arrpath, mygraph.nvertexcount );
//printresult( arrdis, arrpath, mygraph.nvertexcount );
//system( "pause" );
return 0;
}
執行結果如下:
學習參考:
一步步學演算法 演算法分析 6 Floyd演算法
floyd 演算法floyd演算法又稱為 弗洛伊德演算法 插點法,是一種用於尋找給定的 加權圖中頂點間 最短路徑 的演算法。該 演算法名稱以創始人之一 1978年圖靈獎獲得者 史丹福大學電腦科學系教授 羅伯特 弗洛伊德 命名。正如我們所知道的,floyd演算法用於求最短路徑。floyd演算法可以說是...
一步步學ROS
最近因為看svo的 裡面用到catkin決定要好好看ros,年前學會基本操作。啟動節點 rosrun package name executable name 檢視節點 rosnode list 注 rosout 節點是乙個特殊的節點,通過 roscore 自動啟動 檢視特定節點的資訊 rosnod...
一步步學彙編(九)call ret
一步步學彙編 九 call ret call和ret指令都是轉移指令,都修改ip,或同時修改cs和ip。經常被用來 實現子程式的設計。ret指令用棧中的資料,修改ip的內容,實現近轉移 retf指令用棧中的資料,修改cs和ip的內容,實現遠轉移 cpu執行ret指令時的操作 1 ip ss 16 s...