ダイクストラ (ダイクストラ アルゴリズム) と最短パス アルゴリズムの JS コード実装を理解する

 1.イラスト例

例 1

        次の図には 4 つの点 ABCD があり、A から各点までの最短経路を求めます。

  • 最初に、最後の A から各点までの最短経路であるレコード (最後にレコード) を準備します。最初は空です。
  •  Aを起点として、AからB、C、Dに直接到達できます。AからBへの経路は2、Cへの経路は5、Dへの経路は3です。「レコード1」は次のようになります。以下に続きます:
  1. A→B:2
  2. A→C:5
  3. A→D:3

        最短パス A→B: 2 を「最後に記録」に移動すると、「最後に記録」は A→B: 2 になります。

  • 地点 B は C に移動できます: B→C: 4、 A から C は B から転送することを選択できます: この時点では A→C: 2+4=6, 6>5 であるため、「レコード 1」は更新されません( B→C:2と仮定すると、この時点ではA→C:2+2=4、4<5、その後「レコード1」を更新: A→C:4 )
  • D点はCに行くことができます:D→C:3、 AからCに移動することを選択できます:このとき、A→C:3+3=6、6>5なので、「レコード1」は更新されていない
  • 点 C には到達可能な点がありません。計算を終了します。
  • 「レコード 1」を「最終的にレコード」に結合します。
  • 最後に、A から各点への最短経路が得られます: A→B: 2、A→C: 5、A→D: 3 (仮定が正しい場合、「最終的な記録」は A→B: 2、A となります) →C:4.A→D:3)

例 2

        次の図に示すように、A から各点までの最短経路を見つけます。

        インスタンス 1 のレコードは最終的にセット S として記録され、最初の S には開始点のみが含まれます。集合 U の始点以外の点を記録します。隣接するノードはパス値を記録でき、隣接しないノードは ∞ として記録されます。すると、次の図は次のように表されます。

        S={ A(0) },U={ B(4), C(2), D(3), E(∞), F(∞), G(∞), H(∞), I(∞ ) }

 最初の一歩:

  • S={ A(0) }
  • U={ B(4), C(2) , D(3), E(∞), F(∞), G(∞), H(∞), I(∞) }

 ステップ 2: C パスは前のステップで最短であり、2 です。

  • S={ A(0), C(2) }
  • U={ B(4), D(3) , E(2+3=5), F(2+2=4), G(∞), H(∞), I(∞) }

 3 番目のステップ: D パスは前のステップで最も短く、3 です。

  • S={ A(0), C(2), D(3) }
  • U={ B(4) , E(5) , F(4) , G(∞) , H(∞) , I(3+5=8) }

 ステップ 4: 前のステップでは、パス B と F が最短であり、4 です。

  • S={ A(0), C(2), D(3),  B(4) }
  • U={ E(5), F(4) , G(4+5=9), H(∞), I(8) }

 ステップ 5: 前のステップの F パスは最短で、4 です。

  • S={ A(0)、C(2)、D(3)、B(4)、F(4) }
  • U={ E(5) , G(9) , H(4+2=6) , I(8) }

 ステップ 6: 前のステップの E パスが最短で、5 です。

  • S={ A(0)、C(2)、D(3)、B(4)、F(4)、E(5) }  
  • U={ G(5+3=8), H(6) , I(8) }

 ステップ 7: 前のステップの H パスは最短で、6 です。

  • S={ A(0)、C(2)、D(3)、B(4)、F(4)、E(5)、H(6 )  }
  • U={ G(6+1=7) , I(8) }

 ステップ 8: 前のステップの G パスは最短で、7 です。

  • S={ A(0), C(2), D(3), B(4), F(4), E(5), H(6), G(7 )  }
  • U={ I(8) }

 ステップ 9: 前のステップの I パスは最短で、8 です。

  • S={ A(0)、C(2)、D(3)、B(4)、F(4)、E(5)、H(6)、G(7)、I(8  ) }
  • U={ }

これまでに、A から各点までの最短経路が得られました。

2、JSコードの実装

例としてインスタンス 2 を取り上げます。

  • まず、各点までの距離を記録するグラフ配列を定義します。次に例を示します。
  1. A→Aの距離は0、A→Bの距離は4、A→Cの距離は2、A→Dの距離は3、A→Eは隣接していないので距離は0・・・。
  2. B→Aは不可逆なので距離は0、B→Bの距離は0、B→Cの距離は1、B→Dは隣接していないので距離は0…。

        等々

let graph = [
    [0,4,2,3,0,0,0,0,0],
    [0,0,1,0,0,0,5,0,0],
    [0,0,0,0,3,2,0,0,0],
    [0,0,1,0,0,1,0,0,5],
    [0,0,0,0,0,0,3,2,0],
    [0,0,0,0,1,0,0,2,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,0]
]
  • 現在知られている最短パスを記録する currentMinPth 配列を定義し、初期値は無限大です。visited 配列を定義し、それが訪問されたかどうかを記録し、訪問された次のサイクルは訪問しません。
    let currentMinPth = [];
    let visited = [];
    for(let i = 0; i < graph.length;i++){
        currentMinPth.push(INF);
        visited.push(false);
    }
  • 開始点は A で、A→A は 0 なので、currentMinPth[0] は 0 になります。
  • 現在既知のノードから最も近いノードを検索し、インデックス値 minIndex を返します (毎回最短パスから開始)
function getMinIndex(currentMinPth,visited){
    let min = INF;
    let minIndex = -1;
    for(let i = 0; i < currentMinPth.length;i++){
        if(!visited[i]&&currentMinPth[i]<min){
            min = currentMinPth[i];
            minIndex = i;
        }
    }
    return minIndex
}
  • 取得した最も近いノードを訪問済みとして設定します。
visited[minIndex] = true;
  • 隣接ノード、つまり、graph[minIndex][i] !== 0 であるノードを検索し、隣接ノードへのパス値を currentMinPth に更新します。ただし、この値が現在の値より小さい場合に限ります。
if(!visited[i]&&
   graph[minIndex][i] !== 0 && 
   currentMinPth[minIndex] + graph[minIndex][i] < currentMinPth[i]){
   currentMinPth[i] = currentMinPth[minIndex] + graph[minIndex][i];
}
  • currentMinPth の各項目に対して上記のプロセスを繰り返します。長さ - 1 で十分です。最後の 1 つだけが残っている場合はチェックする必要はありません。完全なコードは次のとおりです。
let graph = [
    [0,4,2,3,0,0,0,0,0],
    [0,0,1,0,0,0,5,0,0],
    [0,0,0,0,3,2,0,0,0],
    [0,0,1,0,0,1,0,0,5],
    [0,0,0,0,0,0,3,2,0],
    [0,0,0,0,1,0,0,2,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,0]
]
let INF = Number.MAX_SAFE_INTEGER;
function handlePath(){
    let currentMinPth = [];
    let visited = [];
    for(let i = 0; i < graph.length;i++){
        currentMinPth.push(INF);
        visited.push(false);
    }
    currentMinPth[0] = 0
    for(let j = 0; j < currentMinPth.length - 1;j++){
        let minIndex = getMinIndex(currentMinPth,visited);
        visited[minIndex] = true;
        for(let i = 0; i < currentMinPth.length;i++){
            if(!visited[i]&&
               graph[minIndex][i] !== 0 && 
               currentMinPth[minIndex] + graph[minIndex][i] < currentMinPth[i]){
               currentMinPth[i] = currentMinPth[minIndex] + graph[minIndex][i];
            }
        }
    }
    
    return currentMinPth
}
function getMinIndex(currentMinPth,visited){
    let min = INF;
    let minIndex = -1;
    for(let i = 0; i < currentMinPth.length;i++){
        if(!visited[i]&&currentMinPth[i]<min){
            min = currentMinPth[i];
            minIndex = i;
        }
    }
    return minIndex
}
console.log(handlePath())

要約する

        この記事はダイクストラの最短経路原理の簡単な理解とjsのコード実装を記録したものです、間違いがあればご指摘ください!

おすすめ

転載: blog.csdn.net/sxww_zyt/article/details/129835779