Base/Knowledges/IT/Алгоритмы/Поиск/Алгоритм Дейкстры (Dijkstra's algorithm).md
2026-02-23 19:52:05 +03:00

3.8 KiB
Raw Blame History

#алгоритмы #поиск

!dijkstra.gif

В алгоритме Дейкстры каждому сегменту присваивается число (вес), а алгоритм Дейкстры находит путь с наименьшим суммарным весом

!Pasted image 20250116202010.png

Алгоритм Дейкстры работает только с графами, в которых нет циклов, где все ребра неотрицательны

Cостоит из четырех шагов:

  1. Найти узел с наименьшей стоимостью (то есть узел, до которого можно добраться за минимальное время)
  2. Обновить стоимости соседей этого узла
  3. Повторять, пока это не будет сделано для всех узлов графа
  4. Вычислить итоговый путь

!Pasted image 20250116203308.png

Для реализации понадобятся три хеш-таблицы: граф, родители, стоимости. Хеш таблицы стоимостей и родителей будут обновляться по ходу работы алгоритма.

!Pasted image 20250116203221.png

Существует более эффективный вариант этого алгоритма. Он использует структуру данных, называемую очередью с приоритетом. Эта очередь строится на основе другой структуры данных — кучи.

const findLowestCostNode = (costs, processed) => {
  let lowestCost = Infinity;
  let lowestCostNode = null;

  Object.entries(costs).forEach(([node, cost]) => {
    if (!processed.includes(node) && cost < lowestCost) {
      lowestCost = cost;
      lowestCostNode = node;
    }
  });

  return lowestCostNode;
};

const dejsktra = (graph, [from, to]) => {
  const costs = {
    [to]: Infinity,
    ...graph[from],
  };

  const parents = {};
  Object.keys(graph[from]).forEach(key => parents[key] = from);

  const processed = [];

  let lowestCostNode = from;
  while(lowestCostNode) {
    const neighbours = graph[lowestCostNode] || {};
    Object.keys(neighbours).forEach(neighbour => {
      let cost = costs[lowestCostNode] + neighbours[neighbour];
      
      if (!costs[neighbour]) {
        costs[neighbour] = Infinity;
      }

      if (cost < costs[neighbour]) {
        costs[neighbour] = cost;
        parents[neighbour] = lowestCostNode;
      }
    })

    processed.push(lowestCostNode);
    lowestCostNode = findLowestCostNode(costs, processed);
  }

  const path = [to];
  let parent = parents[to];
  
  while (parent) {
    path.push(parent);
    parent = parents[parent];
  }

  return {
    value: costs[to],
    path: path.reverse()
  }
};


const testGraph = {
  a: { b: 2, f: 6 },
  b: { c: 4 },
  c: { d: 8, g: 6 },
  d: { h: 3 },
  e: { b: 1, g: 5, },
  f: { e: 1, g: 7 },
  g: { d: 2, h: 4, j: 2,},
  h: { j: 1 },
};

const complexGraph = {
  a: { b: 4, c: 2, d: 7 },
  b: { e: 3, f: 1, g: 5 },
  c: { f: 4, h: 2 },
  d: { h: 6, i: 3 },
  e: { j: 2, k: 4 },
  f: { j: 5, l: 2 },
  g: { k: 3, m: 4 },
  h: { l: 5, n: 2 },
  i: { n: 4, o: 3 },
  j: { m: 1, n: 6 },
  k: { n: 2, o: 5 },
  l: { o: 4 },
  m: { o: 3 },
  n: { o: 2 },
  o: {}
};

console.log(dejsktra(testGraph, ['a', 'j']));     // { value: 14, path: [ 'a', 'b', 'c', 'g', 'j' ] }
console.log(dejsktra(complexGraph, ['a', 'o'])); // { value: 8, path: [ 'a', 'c', 'h', 'n', 'o' ] }

Связаные темы:

Источники: