floydwarshall演算法(弗洛伊德演算法)的理解,就一句話
阿新 • • 發佈:2019-02-03
floydwarshall algorithm(弗洛伊德演算法):對每一個頂點,都要嘗試它作為任一對頂點的中轉頂點的可能性。基於此,形成一個基礎資料庫。在這個基礎資料庫的基礎上,追溯出任意兩點的最短路徑。
對幾個疑問的解釋:
1.簡單的迴圈條件,如for (k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
是否會造成頂點的覆疊?比如k=1;i=0;j=1;
解釋:覆疊是會的。但是如例中情況,我們認為k=1,是i=0和j=1的中轉頂點。因而,和總體的原則是統一的,不會影響結果。
2.為什麼會要先有一個全面的基礎資料庫,不能直接得出任意兩點的最短路徑嗎?
答:任意兩點的路徑,它們之間可能有中轉頂點,也可能沒有。但是它們的中轉頂點之間,可能還有其他中轉頂點;其他中轉頂點之間,可能還有其他其他中轉頂點......因此,雖然只是兩個頂點的最短路徑問題,但是關乎全域性的頂點對之間的中轉資訊。因此,需要一個全面的包含所有的中轉頂點的基礎資料庫。
下面是floydwarshall algorithm(弗洛伊德演算法)的c語言程式碼。在最後追溯兩點之間的中間頂點的時候,我沒有用棧,而是用的遞迴函式。
#include "stdio.h" #define NUM 4 #define CN ( (NUM-1)+1 )*NUM/2 void short_path(int E[NUM][NUM],int u,int v); void trace_back(int path[][NUM],int u,int v); main() { int n; n = NUM; int E[n][n]; int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) if (i==j) E[i][j]=0; int ni[CN]={3,10,18,6,15,2};//necessary information; int k; k=0; for (i=0;i<n;i++) for(j=i+1;j<n;j++) E[i][j] = ni[k++]; for(j=0;j<n;j++) for(i=j+1;i<n;i++) E[i][j] = E[j][i]; for (i=0;i<n;i++) for(j=0;j<n;j++) if (j == n-1) printf("%-2d\n",E[i][j]); else printf("%-2d ", E[i][j]); short_path(E,0,3); } void short_path(int E[NUM][NUM],int u,int v) { int n; n=NUM; int dist[NUM][NUM]; int path[NUM][NUM]; int i,j,k; for(i=0;i<n;i++) for(j=0;j<n;j++) dist[i][j]=E[i][j]; for(i=0;i<n;i++) for(j=0;j<n;j++) path[i][j]=-1; for(k=0;k<n;k++) for(i=0;i<n;i++) for(j=0;j<n;j++) if(dist[i][k]+dist[k][j]< dist[i][j]) {dist[i][j] = dist[i][k]+dist[k][j]; path[i][j] = k;} printf("%d ",u); trace_back(path,u,v); } void trace_back(int path[][NUM],int u,int v) { if(path[u][v] != -1) trace_back(path,u,path[u][v]); printf("%d ",v); }