1. 程式人生 > >JavaScript與Floyd最短路演算法

JavaScript與Floyd最短路演算法

背景

NBA超級後場組合燈泡組合(Harden和CP3)休賽期來到中國玩耍,他們兩人打算在四個城市進行玩耍,最後他們選擇了北京、上海、西安和長沙。假設這四個城市之間有些城市之前有航線,而有些城市之間沒有航線。為了方便行程,出發前,他們想要知道任意兩個城市之間的最短路程。如果下圖就是航線圖:

這裡寫圖片描述

資料結構

我們使用一個二維陣列Path來儲存上述圖的資訊。比如說0號城市到1號城市之間的距離可以儲存為Path[0][1] = 2,而1號城市無法直接到達0號城市我們記Path[1][0] = Infinity。另外我們約定一個城市到達本身的距離為0,即Path[0][0] = 0

思路

想要使兩個城市(x

y)之間的距離變短,此時我們可以引入第三個城市作為中轉點(z),本來是x->y,現在變成x->z->y,只有這樣才有可能縮短xy之間的距離,那麼這個中轉點z到底是哪個城市,或者可以說這個z代表的是多箇中轉點,因為有時候經過多箇中轉點,x*y之間的距離會更短。下面我們通過一步步的新增中轉點,來更新兩點之間的最短距離。

過程

我們依照最上面的航線圖,解釋如何得到最短路徑。
當任意兩個城市之間不允許經過第三個城市的時候,得到的矩陣如下:

這裡寫圖片描述

第一步:
現在我們只允許經過0號城市這個中轉點,這個時候如何求解任意兩點之間的最短距離。我們只需進行如下比較:

Path[i
][0] + Path[0][j] < Path[i][j]

其中Path[i][j]表示的是城市ij之間的距離。而Path[i][0] + Path[0][j] 表示的是先從i0號城市,再從0j的距離之和。
這個時候把i0~n-1迴圈,把j0~n-1迴圈,既可以得到當經過中轉點0號城市的時候,任意兩點之間的最短距離。

程式碼實現:

for(var i = 0; i < n; i++ ){
    for(var j = 0; j < n; j++){
        if(Path[i][0] + Path[0][j] < Path[i][j]){
            Path[i][j] = Path[i][0
] + Path[0][j]; } } }

這個時候我們可以把最短距離矩陣更新為:

這裡寫圖片描述

從上圖可以看出,在經過中轉點:0號城市的時候,有幾個城市之間的最短距離減少了。

接下來,我們要做的就是增加中轉點:1號城市。要執行的程式碼如下:

for(var i = 0; i < n; i++ ){
    for(var j = 0; j < n; j++){
        if(Path[i][0] + Path[0][j] < Path[i][j]){
            Path[i][j] = Path[i][0] + Path[0][j];
        }
    }
}
for(var i = 0; i < n; i++ ){
    for(var j = 0; j < n; j++){
        if(Path[i][1] + Path[1][j] < Path[i][j]){
            Path[i][j] = Path[i][1] + Path[1][j];
        }
    }
}

我們可以繼續更新距離矩陣為:

這裡寫圖片描述

從上圖可以看出,增加中轉點後,有些城市之間的最短距離進一步減小。

同理,我們進一步增加中轉點城市2和城市3,就可以得到最終的距離矩陣為:

這裡寫圖片描述

下面給出一個完整函式:

//接收一個引數,引數即用二維陣列儲存的距離矩陣
function floyd(Path){
    var n = Path && Path.length;
    var m = n && Path[0].length;
    if(m && n && m===n){
        for(var k = 0; k < n; k++){
            for(var i = 0; i < n; i++ ){
                for(var j = 0; j < n; j++){
                    if(Path[i][k] + Path[k][j] < Path[i][j]){
                        Path[i][j] = Path[i][k] + Path[k][j];
                    }
                }
            }
        }
    }
}

注意:Floyd演算法不能解決帶有“負權迴路”(或者叫“負權環”)的圖。因為帶有“負權迴路”的圖沒有最短路。