forked from mburst/dijkstras-algorithm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dijkstras.js
103 lines (85 loc) · 2.45 KB
/
dijkstras.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* Basic priority queue implementation. If a better priority queue is wanted/needed,
* this code works with the implementation in google's closure library (https://code.google.com/p/closure-library/).
* Use goog.require('goog.structs.PriorityQueue'); and new goog.structs.PriorityQueue()
*/
function PriorityQueue () {
this._nodes = [];
this.enqueue = function (priority, key) {
this._nodes.push({key: key, priority: priority });
this.sort();
};
this.dequeue = function () {
return this._nodes.shift().key;
};
this.sort = function () {
this._nodes.sort(function (a, b) {
return a.priority - b.priority;
});
};
this.isEmpty = function () {
return !this._nodes.length;
};
}
/**
* Pathfinding starts here
*/
function Graph(){
var INFINITY = 1/0;
this.vertices = {};
this.addVertex = function(name, edges){
this.vertices[name] = edges;
};
this.shortestPath = function (start, finish) {
var nodes = new PriorityQueue(),
distances = {},
previous = {},
path = [],
smallest, vertex, neighbor, alt;
for(vertex in this.vertices) {
if(vertex === start) {
distances[vertex] = 0;
nodes.enqueue(0, vertex);
}
else {
distances[vertex] = INFINITY;
nodes.enqueue(INFINITY, vertex);
}
previous[vertex] = null;
}
while(!nodes.isEmpty()) {
smallest = nodes.dequeue();
if(smallest === finish) {
path = [];
while(previous[smallest]) {
path.push(smallest);
smallest = previous[smallest];
}
break;
}
if(!smallest || distances[smallest] === INFINITY){
continue;
}
for(neighbor in this.vertices[smallest]) {
alt = distances[smallest] + this.vertices[smallest][neighbor];
if(alt < distances[neighbor]) {
distances[neighbor] = alt;
previous[neighbor] = smallest;
nodes.enqueue(alt, neighbor);
}
}
}
return path;
};
}
var g = new Graph();
g.addVertex('A', {B: 7, C: 8});
g.addVertex('B', {A: 7, F: 2});
g.addVertex('C', {A: 8, F: 6, G: 4});
g.addVertex('D', {F: 8});
g.addVertex('E', {H: 1});
g.addVertex('F', {B: 2, C: 6, D: 8, G: 9, H: 3});
g.addVertex('G', {C: 4, F: 9});
g.addVertex('H', {E: 1, F: 3});
// Log test, with the addition of reversing the path and prepending the first node so it's more readable
console.log(g.shortestPath('A', 'H').concat(['A']).reverse());