97 lines
2.4 KiB
JavaScript
97 lines
2.4 KiB
JavaScript
// 1) Найти самый дешевый узел из необработанных
|
||
// 2) Проверить минимальный путь до его соседей и обновить стоимость и родителя
|
||
// 3) Пометить узел как обработанный
|
||
// 4) Продолжать пока все узлы не будут обработаны
|
||
// 5) Вернуть итоговую стоимость и путь
|
||
|
||
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' ] }
|