JavaScriptは最短パスアルゴリズムを実現します.

3886 ワード

2点の間の最短距離を求める最も一般的なアルゴリズム:DijkstraアルゴリズムとFloyd-Warshallアルゴリズム.
1、Dijkstraアルゴリズム
単一のソースには図への最短のパス問題があり、時間の複雑さはO(n 2)、nは頂点の数であり、他の頂点から始まるならば、元のアルゴリズムに基づいてもう一度循環します.この時間の複雑さはO(n 3)です.スタート地点を中心に外に向かって幾重にも広がっているのが特徴です.
基本思想
図Gにおける最短経路をDijkstraで計算する場合は、始点sを指定する必要があります.すなわち、頂点sから計算します.また、2つのセットSとUを導入します.Sの役割は、最も短い経路が求められた頂点(及び、対応する最短経路長)を記録することであり、Uは、最も短い経路が求められていない頂点(及び、頂点から起点sまでの距離)を記録することである.初期時は、Sでは起点sのみとなります.Uはs以外の頂点であり、Uの頂点の経路は「始点sから頂点までの経路」である.そして、Uから最短の経路の頂点を探し出し、Sに加える.次に、Uの頂点と頂点に対応する経路を更新する.そして、Uから最短の経路の頂点を探し出し、Sに加える.次に、Uの頂点と頂点に対応する経路を更新する.すべての頂点を巡回するまで、この操作を繰り返します.
Dijkstraアルゴリズムの図解
コードの実装:
const INF = Number.MAX_SAFE_INTEGER;
//       
const minDistance = (dist, visited) => {
  let min = INF;
  let minIndex = -1;
  for (let v = 0; v < dist.length; v++) {
    if (visited[v] === false && dist[v] <= min) {
      min = dist[v];
      minIndex = v;
    }
  }
  return minIndex;
};
/** 
 * @param { :    } graph 
 * @param {    } src 
 */
export const dijkstra = (graph, src) => {
  const dist = [];
  //        src             
  const visited = [];
  const { length } = graph; 
  for (let i = 0; i < length; i++) {
    dist[i] = INF;
    visited[i] = false;
  }
  dist[src] = 0;
  for (let i = 0; i < length - 1; i++) {
    const u = minDistance(dist, visited);
    //      src            
    visited[u] = true;
    for (let v = 0; v < length; v++) {
      if (!visited[v] && graph[u][v] !== 0 && dist[u] !== INF && dist[u] + graph[u][v] < dist[v]) {
        //    dist
        dist[v] = dist[u] + graph[u][v];
      }
    }
  }
  return dist;
};

// test 
const graph = [
    [0, 2, 4, 0, 0, 0],
    [0, 0, 2, 4, 2, 0],
    [0, 0, 0, 0, 3, 0],
    [0, 0, 0, 0, 0, 2],
    [0, 0, 0, 3, 0, 2],
    [0, 0, 0, 0, 0, 0]
];

const dist = dijkstra(graph, 0);
for (i = 0; i < dist.length; i++) {
    console.log(i + '\t\t' + dist[i]);
}
// result
0       0
1       2
2       4
3       6
4       4
5       6
2、Floyd-Warshallアルゴリズム
Floyd-Warshallアルゴリズムは古典的な動的計画アルゴリズムである.すべての頂点間の最短経路問題を解決し、時間の複雑度はO(n 3)、nはトップポイントです.図または負の権利を持つ最短の経路問題を正確に処理することができる.
基本思想
任意のノードiから任意のノードjまでの最短経路が要求され、Dis(i,j)がノードuからノードvまでの最短経路の距離であると仮定して、各ノードkに対して、Dis(i,k)+Dis(k,j)<Dis(i,j)が成立しているかどうかを確認し、成立すれば、iからkまでの経路がiより直接jまでの経路が短いことを証明し、Disk(Disk+j)を設定する(Disk(Disk).このようにして、すべてのノードkを遍歴したとき、Dis(i,j)に記録されたiからjまでの最短経路の距離が記録される.
Floyd-Warshallアルゴリズム図解
コードの実装:
export const floydWarshall = graph => {
  const dist = [];
  const { length } = graph;
  //        
  for (let i = 0; i < length; i++) {
    dist[i] = [];
    for (let j = 0; j < length; j++) {
      if (i === j) {
        dist[i][j] = 0;
      } else if (!isFinite(graph[i][j])) {
        dist[i][j] = Infinity;
      } else {
        dist[i][j] = graph[i][j];
      }
    }
  }
  for (let k = 0; k < length; k++) {
    for (let i = 0; i < length; i++) {
      for (let j = 0; j < length; j++) {
        //         k              ,              
        if (dist[i][k] + dist[k][j] < dist[i][j]) {
          dist[i][j] = dist[i][k] + dist[k][j];
        }
      }
    }
  }
  return dist;
};

// test
const INF = Infinity;
const graph = [
  [INF, 2, 4, INF, INF, INF],
  [INF, INF, 2, 4, 2, INF],
  [INF, INF, INF, INF, 3, INF],
  [INF, INF, INF, INF, INF, 2],
  [INF, INF, INF, 3, INF, 2],
  [INF, INF, INF, INF, INF, INF]
];

dist = floydWarshall(graph);

let s = '';
for (let i = 0; i < dist.length; ++i) {
  s = '';
  for (var j = 0; j < dist.length; ++j) {
    if (dist[i][j] === INF) s += 'INF ';
    else s += dist[i][j] + '   ';
  }
  console.log(s);
}
// result
0   2   4   6   4   6   
INF 0   2   4   2   4   
INF INF 0   6   3   5   
INF INF INF 0   INF 2   
INF INF INF 3   0   2   
INF INF INF INF INF 0
参考:単一ソースの最短パスの実証