Floyd最短路徑演算法
阿新 • • 發佈:2018-12-13
使用帶權圖的鄰接矩陣方法表示圖並且不能有負週期。如:
g = [
[0,1,float('inf'),1,5],
[9,0,3,2,float('inf')],
[float('inf'),float('inf'),0,4,float('inf')],
[float('inf'),float('inf'),2,0,3],
[3,float('inf'),float('inf'),float('inf'),0]
]
其中g[i][j]表示i到j邊的權重。
Floyd方法指的是如果要從N個結點中找一條i,j兩點之間的最短路徑,首先對比兩點之間的距離與經過剩餘N-2個結點中任意一個結點k1的距離:
g[i][j]=min(g[i][j],g[i][k1]+g[k1][j])
即從i到j中途經過點k1的距離與g[i][j]進行對比,選取較小的值作為經過中途經過一個點的最短路徑。
接下來計算中途經過k1和k2兩個點時的情況,由於已經有了經過一個點時的結果,就可以在此基礎上計算經過兩個點時的最短路徑。經過兩個點時我們比較的是以下路徑中的最小值:
g[i][j]
g[i][k1] + g[k1][j]
g[i][k2] + g[k2][j]
g[i][k1] + g[k1][k2] + g[k2][j]
g[i][k2] + g[k2][k1] + g[k1][j]
由於我們有了以下經過第一個點k1時的結論:
g[i][j] = min(g[i][j] 或g[i][k1] + g[k1][j]) ···········1
g[i][k2] = min(g[i][k2]或g[i][k1] + g[k1][k2]) ···········2
g[k2][j] = min(g[k2][j]或g[k2][k1] + g[k1][j]) ···········3
經過兩個點時:
g[i][j] = min(g[i][j]或g[i][k2] + g[k2][j]) 由1、2、3得: g[i][j] = min(g[i][j] g[i][k1] + g[k1][j] g[i][k2] + g[k2][j] g[i][k1] + g[k1][k2] + g[k2][j] g[i][k2] + g[k2][k1] + g[k1][j])
因此我們得到一般性規律,找圖中兩點i,j的最短路徑時,可先考慮兩點加任一點k1,找出圖中任意兩點經過點k1的最短路徑並生成經過k1後的圖的最短路徑矩陣。之後引入除i,j,k1點外的任一點k2,由於在經過k1的最短路徑矩陣的基礎上計算經過兩點的最短路徑,可以直接重複第一步的過程。
完整Python程式碼如下:
graph = [
[0,1,float('inf'),1,5],
[9,0,3,2,float('inf')],
[float('inf'),float('inf'),0,4,float('inf')],
[float('inf'),float('inf'),2,0,3],
[3,float('inf'),float('inf'),float('inf'),0]
]
n = len(graph)
for k in range(n): //經過的每個點
for i in range(n):
for j in range(n):
if graph[i][j] > graph[i][k] + graph[k][j]: //判斷點i,j經過第0到第k-1個點時的最短路徑
graph[i][j] = graph[i][k] + graph[k][j]
print(graph)
其中核心程式碼只有五行三重迴圈,時間複雜度為n³,n為輸入圖的結點數。如果資料量很小或對時間要求不高時,可以使用此簡單方法生成最短路徑。