Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create dijkstra.js #102

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions Javascript/Stack/dijkstra.js
Original file line number Diff line number Diff line change
@@ -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,
};
}