125 lines
3.8 KiB
Markdown
125 lines
3.8 KiB
Markdown
#алгоритмы #поиск
|
||
|
||
![[dijkstra.gif]]
|
||
|
||
> В алгоритме Дейкстры каждому сегменту присваивается число (вес), а алгоритм Дейкстры находит путь с наименьшим суммарным весом
|
||
|
||
![[Pasted image 20250116202010.png]]
|
||
|
||
Алгоритм Дейкстры работает только с графами, в которых нет циклов, где
|
||
все ребра неотрицательны
|
||
|
||
Cостоит из четырех шагов:
|
||
1. Найти узел с наименьшей стоимостью (то есть узел, до которого можно добраться за минимальное время)
|
||
2. Обновить стоимости соседей этого узла
|
||
3. Повторять, пока это не будет сделано для всех узлов графа
|
||
4. Вычислить итоговый путь
|
||
|
||
![[Pasted image 20250116203308.png]]
|
||
|
||
Для реализации понадобятся три хеш-таблицы: граф, родители, стоимости. Хеш таблицы стоимостей и родителей будут обновляться по ходу работы алгоритма.
|
||
|
||
![[Pasted image 20250116203221.png]]
|
||
|
||
Существует более эффективный вариант этого алгоритма. Он использует структуру данных, называемую очередью с приоритетом. Эта очередь строится на основе другой структуры данных — кучи.
|
||
|
||
```javascript
|
||
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' ] }
|
||
```
|
||
|
||
Связаные темы:
|
||
- [[Граф (Graph)]]
|
||
- [[Поиск в ширину (Breadth-first search)]]
|
||
|
||
Источники:
|
||
- [[Адитья Бхаргава - Грокаем Алгоритмы]] |