56 lines
1.5 KiB
JavaScript
56 lines
1.5 KiB
JavaScript
|
const Queue = require('./queue');
|
||
|
const Graph = require('./graph');
|
||
|
|
||
|
function findPathWithDijkstra(cities, roads, startNode, endNode) {
|
||
|
const graph = new Graph();
|
||
|
|
||
|
// Add cities and roads to graph
|
||
|
for (let city of cities) {
|
||
|
graph.addNode(city.id)
|
||
|
}
|
||
|
|
||
|
for (let { start_city_id, end_city_id, distance } of roads) {
|
||
|
graph.addEdge(start_city_id, end_city_id, distance)
|
||
|
}
|
||
|
|
||
|
// Dijkstra path search algo
|
||
|
let times = {};
|
||
|
let backtrace = {};
|
||
|
let queue = new Queue();
|
||
|
|
||
|
times[startNode] = 0;
|
||
|
|
||
|
graph.nodes.forEach(node => {
|
||
|
if (node !== startNode) {
|
||
|
times[node] = Infinity
|
||
|
}
|
||
|
});
|
||
|
|
||
|
queue.enqueue([startNode, 0]);
|
||
|
|
||
|
while (queue.size()) {
|
||
|
let shortestStep = queue.dequeue();
|
||
|
let currentNode = shortestStep[0];
|
||
|
graph.adjacencyList[currentNode].forEach(neighbor => {
|
||
|
let time = times[currentNode] + neighbor.distance;
|
||
|
|
||
|
if (time < times[neighbor.node]) {
|
||
|
times[neighbor.node] = time;
|
||
|
backtrace[neighbor.node] = currentNode;
|
||
|
queue.enqueue([neighbor.node, time]);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
let path = [endNode];
|
||
|
let lastStep = endNode; while(lastStep !== startNode) {
|
||
|
path.unshift(backtrace[lastStep])
|
||
|
lastStep = backtrace[lastStep]
|
||
|
}
|
||
|
|
||
|
// return `Path is ${path} and time is ${times[endNode]}`
|
||
|
return {path, distance: times[endNode]}
|
||
|
}
|
||
|
|
||
|
module.exports = findPathWithDijkstra;
|