JS實現最短路徑之弗洛伊德(Floyd)算法


  弗洛伊德算法是實現最小生成樹的一個很精妙的算法,也是求所有頂點至所有頂點的最短路徑問題的不二之選。時間復雜度為O(n3),n為頂點數。

  精妙之處在於:一個二重初始化,加一個三重循環權值修正,完成了所有頂點至所有頂點的的最短路徑計算,代碼及其簡潔

 

JS實現:

//定義鄰接矩陣
let Arr2 = [
    [0, 1, 5, 65535, 65535, 65535, 65535, 65535, 65535],
    [1, 0, 3, 7, 5, 65535, 65535, 65535, 65535],
    [5, 3, 0, 65535, 1, 7, 65535, 65535, 65535],
    [65535, 7, 65535, 0, 2, 65535, 3, 65535, 65535],
    [65535, 5, 1, 2, 0, 3, 6, 9, 65535],
    [65535, 65535, 7, 65535, 3, 0, 65535, 5, 65535],
    [65535, 65535, 65535, 3, 6, 65535, 0, 2, 7],
    [65535, 65535, 65535, 65535, 9, 5, 2, 0, 4],
    [65535, 65535, 65535, 65535, 65535, 65535, 7, 4, 0],
]

let numVertexes = 9, //定義頂點數
    numEdges = 15; //定義邊數

// 定義圖結構  
function MGraph() {
    this.vexs = []; //頂點表
    this.arc = []; // 鄰接矩陣,可看作邊表
    this.numVertexes = null; //圖中當前的頂點數
    this.numEdges = null; //圖中當前的邊數
}
let G = new MGraph(); //創建圖使用

//創建圖
function createMGraph() {
    G.numVertexes = numVertexes; //設置頂點數
    G.numEdges = numEdges; //設置邊數

    //錄入頂點信息
    for (let i = 0; i < G.numVertexes; i++) {
        G.vexs[i] = 'V' + i; //scanf('%s'); //ascii碼轉字符 //String.fromCharCode(i + 65);
    }
    console.log(G.vexs) //打印頂點

    //鄰接矩陣初始化
    for (let i = 0; i < G.numVertexes; i++) {
        G.arc[i] = [];
        for (j = 0; j < G.numVertexes; j++) {
            G.arc[i][j] = Arr2[i][j]; //INFINITY; 
        }
    }
    console.log(G.arc); //打印鄰接矩陣
}

let Pathmatirx = []; //二維數組 表示頂點到頂點的最短路徑權值和的矩陣
let ShortPathTable = []; //二維數組 表示對應頂點的最小路徑的前驅矩陣

function Floyd() {

    let w, k;
    for (let v = 0; v < G.numVertexes; ++v) { //初始化 Pathmatirx ShortPathTable
        Pathmatirx[v] = [];
        ShortPathTable[v] = [];
        for (let w = 0; w < G.numVertexes; ++w) {
            ShortPathTable[v][w] = G.arc[v][w];
            Pathmatirx[v][w] = w;
        }
    }

    for (let k = 0; k < G.numVertexes; ++k) {
        for (let v = 0; v < G.numVertexes; ++v) {
            for (let w = 0; w < G.numVertexes; ++w) {
                if (ShortPathTable[v][w] > (ShortPathTable[v][k] + ShortPathTable[k][w])) {
                    //如果經過下標為k頂點路徑比原兩點間路徑更短,當前兩點間權值設為更小的一個
                    ShortPathTable[v][w] = ShortPathTable[v][k] + ShortPathTable[k][w];
                    Pathmatirx[v][w] = Pathmatirx[v][k]; //路徑設置經過下標為k的頂點
                }
            }
        }
    }
}

function PrintAll() {
    for (let v = 0; v < G.numVertexes; ++v) {
        for (let w = v + 1; w < G.numVertexes; w++) {
            console.log('V%d-V%d weight: %d', v, w, ShortPathTable[v][w]);
            k = Pathmatirx[v][w];
            console.log(' Path: %d', v);
            while (k != w) {
                console.log(' -> %d', k);
                k = Pathmatirx[k][w];
            }
            console.log(' -> %d', w);
        }
    }
}

createMGraph();
Floyd();
PrintAll();

運行結果:(結果太長只截取不分)

 

求最短路徑的兩個算法(迪傑斯特拉算法和弗洛伊德算法),對有向圖依然有效,因為者的差異僅僅是鄰接矩陣是否對稱而已

 

參考文獻: 程傑 《大話設計模式》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM