Add more comments for Dijkstra.

This commit is contained in:
Oleksii Trekhleb 2019-03-03 09:58:02 +02:00
parent 1f393551c7
commit 881e3ae5aa

View File

@ -1,30 +1,44 @@
import PriorityQueue from '../../../data-structures/priority-queue/PriorityQueue'; import PriorityQueue from '../../../data-structures/priority-queue/PriorityQueue';
/** /**
* @param {Graph} graph * @typedef {Object} ShortestPaths
* @param {GraphVertex} startVertex * @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) { export default function dijkstra(graph, startVertex) {
// Init helper variables that we will need for Dijkstra algorithm.
const distances = {}; const distances = {};
const visitedVertices = {}; const visitedVertices = {};
const previousVertices = {}; const previousVertices = {};
const queue = new PriorityQueue(); const queue = new PriorityQueue();
// Init all distances with infinity assuming that currently we can't reach // Init all distances with infinity assuming that currently we can't reach
// any of the vertices except start one. // any of the vertices except the start one.
graph.getAllVertices().forEach((vertex) => { graph.getAllVertices().forEach((vertex) => {
distances[vertex.getKey()] = Infinity; distances[vertex.getKey()] = Infinity;
previousVertices[vertex.getKey()] = null; previousVertices[vertex.getKey()] = null;
}); });
// We are already at the startVertex so the distance to it is zero.
distances[startVertex.getKey()] = 0; distances[startVertex.getKey()] = 0;
// Init vertices queue. // Init vertices queue.
queue.add(startVertex, distances[startVertex.getKey()]); queue.add(startVertex, distances[startVertex.getKey()]);
// Iterate over the priority queue of vertices until it is empty.
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
// Fetch next closest vertex.
const currentVertex = queue.poll(); const currentVertex = queue.poll();
graph.getNeighbors(currentVertex).forEach((neighbor) => { // Iterate over every unvisited neighbor of the current vertex.
currentVertex.getNeighbors().forEach((neighbor) => {
// Don't visit already visited vertices. // Don't visit already visited vertices.
if (!visitedVertices[neighbor.getKey()]) { if (!visitedVertices[neighbor.getKey()]) {
// Update distances to every neighbor from current vertex. // Update distances to every neighbor from current vertex.
@ -33,15 +47,16 @@ export default function dijkstra(graph, startVertex) {
const existingDistanceToNeighbor = distances[neighbor.getKey()]; const existingDistanceToNeighbor = distances[neighbor.getKey()];
const distanceToNeighborFromCurrent = distances[currentVertex.getKey()] + edge.weight; const distanceToNeighborFromCurrent = distances[currentVertex.getKey()] + edge.weight;
// If we've found shorter path to the neighbor - update it.
if (distanceToNeighborFromCurrent < existingDistanceToNeighbor) { if (distanceToNeighborFromCurrent < existingDistanceToNeighbor) {
distances[neighbor.getKey()] = distanceToNeighborFromCurrent; distances[neighbor.getKey()] = distanceToNeighborFromCurrent;
// Change priority. // Change priority of the neighbor in a queue since it might have became closer.
if (queue.hasValue(neighbor)) { if (queue.hasValue(neighbor)) {
queue.changePriority(neighbor, distances[neighbor.getKey()]); queue.changePriority(neighbor, distances[neighbor.getKey()]);
} }
// Remember previous vertex. // Remember previous closest vertex.
previousVertices[neighbor.getKey()] = currentVertex; previousVertices[neighbor.getKey()] = currentVertex;
} }
@ -52,10 +67,12 @@ export default function dijkstra(graph, startVertex) {
} }
}); });
// Add current vertex to visited ones. // Add current vertex to visited ones to avoid visiting it again later.
visitedVertices[currentVertex.getKey()] = currentVertex; 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 { return {
distances, distances,
previousVertices, previousVertices,