Created
March 18, 2020 09:57
-
-
Save Prottoy2938/f3f51183c29022b02dc20bea460ce0eb to your computer and use it in GitHub Desktop.
Dijkstra's-algorithm implementation in JavaScript. This is the naive version, `PriorityQueue` class can be upgraded to a faster queue.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Helper class. To get the most prioritize result out | |
class PriorityQueue { | |
constructor() { | |
this.values = []; | |
} | |
enqueue(val, priority) { | |
this.values.push({ val, priority }); | |
this.sort(); | |
} | |
dequeue() { | |
return this.values.shift(); | |
} | |
sort() { | |
this.values.sort((a, b) => a.priority - b.priority); | |
} | |
} | |
//Dijsksta's algoritm only works on a weighted-graph. | |
class WeightedGraph { | |
constructor() { | |
this.adjacencyList = {}; | |
} | |
addVertex(vertex) { | |
if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; | |
} | |
addEdge(vertex1, vertex2, weight) { | |
this.adjacencyList[vertex1].push({ node: vertex2, weight }); | |
this.adjacencyList[vertex2].push({ node: vertex1, weight }); | |
} | |
Dijkstra(start, finish) { | |
const nodes = new PriorityQueue(); | |
const distances = {}; | |
const previous = {}; | |
let path = []; //to return at end | |
let smallest; | |
//build up initial state | |
for (let vertex in this.adjacencyList) { | |
if (vertex === start) { | |
distances[vertex] = 0; | |
nodes.enqueue(vertex, 0); | |
} else { | |
distances[vertex] = Infinity; | |
nodes.enqueue(vertex, Infinity); | |
} | |
previous[vertex] = null; | |
} | |
// as long as there is something to visit | |
while (nodes.values.length) { | |
smallest = nodes.dequeue().val; | |
if (smallest === finish) { | |
//WE ARE DONE | |
//BUILD UP PATH TO RETURN AT END | |
while (previous[smallest]) { | |
path.push(smallest); | |
smallest = previous[smallest]; | |
} | |
break; | |
} | |
if (smallest || distances[smallest] !== Infinity) { | |
for (let neighbor in this.adjacencyList[smallest]) { | |
//find neighboring node | |
let nextNode = this.adjacencyList[smallest][neighbor]; | |
//calculate new distance to neighboring node | |
let candidate = distances[smallest] + nextNode.weight; | |
let nextNeighbor = nextNode.node; | |
if (candidate < distances[nextNeighbor]) { | |
//updating new smallest distance to neighbor | |
distances[nextNeighbor] = candidate; | |
//updating previous - How we got to neighbor | |
previous[nextNeighbor] = smallest; | |
//enqueue in priority queue with new priority | |
nodes.enqueue(nextNeighbor, candidate); | |
} | |
} | |
} | |
} | |
return path.concat(smallest).reverse(); | |
} | |
} | |
//EXAMPLE======================================================================================== | |
var graph = new WeightedGraph(); | |
graph.addVertex("A"); | |
graph.addVertex("B"); | |
graph.addVertex("C"); | |
graph.addVertex("D"); | |
graph.addVertex("E"); | |
graph.addVertex("F"); | |
graph.addEdge("A", "B", 4); | |
graph.addEdge("A", "C", 2); | |
graph.addEdge("B", "E", 3); | |
graph.addEdge("C", "D", 2); | |
graph.addEdge("C", "F", 4); | |
graph.addEdge("D", "E", 3); | |
graph.addEdge("D", "F", 1); | |
graph.addEdge("E", "F", 1); | |
console.log(graph.Dijkstra("A", "E")); // [ 'A', 'C', 'D', 'F', 'E' ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment