From 7daf042876ebe4b21a4b1ad98067317cb0216b80 Mon Sep 17 00:00:00 2001 From: Adithya Anilkumar Date: Sat, 30 Oct 2021 19:23:28 +0530 Subject: [PATCH] Create dijkstra.js --- Javascript/Stack/dijkstra.js | 80 ++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Javascript/Stack/dijkstra.js diff --git a/Javascript/Stack/dijkstra.js b/Javascript/Stack/dijkstra.js new file mode 100644 index 0000000..c5b47b0 --- /dev/null +++ b/Javascript/Stack/dijkstra.js @@ -0,0 +1,80 @@ +import PriorityQueue from '../../../data-structures/priority-queue/PriorityQueue'; + +/** + * @typedef {Object} ShortestPaths + * @property {Object} distances - shortest distances to all vertices + * @property {Object} previousVertices - shortest paths to all vertices. + */ + +/** + * Implementation of Dijkstra algorithm of finding the shortest paths to graph nodes. + * @param {Graph} graph - graph we're going to traverse. + * @param {GraphVertex} startVertex - traversal start vertex. + * @return {ShortestPaths} + */ +export default function dijkstra(graph, startVertex) { + // Init helper variables that we will need for Dijkstra algorithm. + const distances = {}; + const visitedVertices = {}; + const previousVertices = {}; + const queue = new PriorityQueue(); + + // Init all distances with infinity assuming that currently we can't reach + // any of the vertices except the start one. + graph.getAllVertices().forEach((vertex) => { + distances[vertex.getKey()] = Infinity; + previousVertices[vertex.getKey()] = null; + }); + + // We are already at the startVertex so the distance to it is zero. + distances[startVertex.getKey()] = 0; + + // Init vertices queue. + queue.add(startVertex, distances[startVertex.getKey()]); + + // Iterate over the priority queue of vertices until it is empty. + while (!queue.isEmpty()) { + // Fetch next closest vertex. + const currentVertex = queue.poll(); + + // Iterate over every unvisited neighbor of the current vertex. + currentVertex.getNeighbors().forEach((neighbor) => { + // Don't visit already visited vertices. + if (!visitedVertices[neighbor.getKey()]) { + // Update distances to every neighbor from current vertex. + const edge = graph.findEdge(currentVertex, neighbor); + + const existingDistanceToNeighbor = distances[neighbor.getKey()]; + const distanceToNeighborFromCurrent = distances[currentVertex.getKey()] + edge.weight; + + // If we've found shorter path to the neighbor - update it. + if (distanceToNeighborFromCurrent < existingDistanceToNeighbor) { + distances[neighbor.getKey()] = distanceToNeighborFromCurrent; + + // Change priority of the neighbor in a queue since it might have became closer. + if (queue.hasValue(neighbor)) { + queue.changePriority(neighbor, distances[neighbor.getKey()]); + } + + // Remember previous closest vertex. + previousVertices[neighbor.getKey()] = currentVertex; + } + + // Add neighbor to the queue for further visiting. + if (!queue.hasValue(neighbor)) { + queue.add(neighbor, distances[neighbor.getKey()]); + } + } + }); + + // Add current vertex to visited ones to avoid visiting it again later. + visitedVertices[currentVertex.getKey()] = currentVertex; + } + + // Return the set of shortest distances to all vertices and the set of + // shortest paths to all vertices in a graph. + return { + distances, + previousVertices, + }; +}