forked from mburst/dijkstras-algorithm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdijkstra.ts
143 lines (119 loc) · 2.76 KB
/
dijkstra.ts
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* A node for priorioty linked list / stack and such
*/
class PriorityNode {
key:number;
priority:number;
constructor(key: number,priority: number){
this.key = key;
this.priority = priority;
}
}
/**
* A priority queue with highest priority always on top
* This queue is sorted by priority for each enqueue
*/
class PriorityQueue {
nodes:PriorityNode[] = [];
/**
* Enqueue a new node
* @param {[type]} priority
* @param {[type]} key
*/
enqueue(priority:number, key:number){
this.nodes.push(new PriorityNode(key, priority));
this.nodes.sort(
function(a, b) {
return a.priority - b.priority;
}
)
}
/**
* Dequeue the highest priority key
*/
dequeue():number{
return this.nodes.shift().key;
}
/**
* Checks if empty
*/
empty():boolean{
return !this.nodes.length;
}
}
/**
* Computes the shortest path between two node
*/
class Dijkstra{
infinity = 1/0;
vertices = {};
/**
* Add a new vertex and related edges
* @param {[type]} name [description]
* @param {[type]} edges [description]
*/
addVertex(name:string, edges:any){
this.vertices[name] = edges;
}
/**
* Computes the shortest path from start to finish
* @param {[type]} start [description]
* @param {[type]} finish [description]
*/
shortestPath(start:string, finish:string){
let nodes = new PriorityQueue(),
distances = {},
previous = {},
path = [],
smallest,
vertex,
neighbor,
alt;
//Init the distances and queues variables
for(vertex in this.vertices){
if(vertex === start){
distances[vertex] = 0;
nodes.enqueue(0, vertex);
}else{
distances[vertex] = this.infinity;
nodes.enqueue(this.infinity, vertex);
}
previous[vertex] = null;
}
//continue as long as the queue haven't been emptied.
while(!nodes.empty()){
smallest = nodes.dequeue();
//we are the last node
if(smallest === finish){
//Compute the path
while(previous[smallest]){
path.push(smallest);
smallest = previous[smallest];
}
break;
}
//No distance known. Skip.
if(!smallest || distances[smallest] === this.infinity){
continue;
}
//Compute the distance for each neighbor
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);
}
}
}
//the starting point isn't in the solution &
//the solution is from end to start.
return path.concat(start).reverse();
}
}
let graph:Dijkstra = new Dijkstra();
graph.addVertex('A', { B: 7, C: 8 });
graph.addVertex('C', { A: 8 });
graph.addVertex('B', { A: 7, F: 8 });
graph.addVertex('F', { B: 8 });
console.log(graph.shortestPath('A', 'F'));