Skip to content

Commit b812d13

Browse files
committed
Dijkstra is added. The heap is modified to be more usable.
1 parent c5bfd88 commit b812d13

3 files changed

Lines changed: 153 additions & 28 deletions

File tree

‎readme.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
Different algorithms implemented in JavaScript
1+
##About
2+
This repository contains different famous Computer Science algorithms implemented in JavaScript
3+
4+
##License
5+
The code in this repository is distributed under the terms of the MIT license.

‎src/data-structures/heap.js‎

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,63 @@
11
/**
2-
* Constructor function of maximum heap
2+
* Constructor function of minimum heap
33
*
44
* @public
5+
* @param {function} Function used for comparition between the elements
56
*/
6-
function MaxHeap() {
7+
function Heap(cmp) {
78
this._heap = [];
9+
if (typeof cmp === 'function') {
10+
this._cmp = cmp;
11+
} else {
12+
this._cmp = function (a, b) {
13+
return a - b;
14+
};
15+
}
816
}
917

1018
/**
1119
* Exchange indexes with start index given as argument
12-
* to turn the heap into valid maxheap. On a single call
20+
* to turn the tree into a valid heap. On a single call
1321
* this method maintains only a single "branch" of the heap. Complexity O(log n)
1422
*
1523
* @private
1624
* @param {number} index The parent
1725
*/
18-
MaxHeap.prototype._heapify = function (index) {
19-
var max = index,
26+
Heap.prototype._heapify = function (index) {
27+
var extr = index,
2028
left = 2 * index + 1,
2129
right = 2 * index + 2,
2230
temp;
2331

24-
if (left < this._heap.length && this._heap[left] > this._heap[index])
25-
max = left;
32+
if (left < this._heap.length && this._cmp(this._heap[left], this._heap[index]) > 0)
33+
extr = left;
2634

27-
if (right < this._heap.length && this._heap[right] > this._heap[index])
28-
max = right;
35+
if (right < this._heap.length && this._cmp(this._heap[right], this._heap[index]) > 0)
36+
extr = right;
2937

30-
if (index !== max) {
38+
if (index !== extr) {
3139
temp = this._heap[index];
32-
this._heap[index] = this._heap[max];
33-
this._heap[max] = temp;
34-
this._heapify(max);
40+
this._heap[index] = this._heap[extr];
41+
this._heap[extr] = temp;
42+
this._heapify(extr);
3543
}
3644

3745
}
3846

3947
/**
40-
* Increases the key for give index. Complexity O(log n).
48+
* Changes the key for give index. Complexity O(log n).
4149
*
4250
* @public
43-
* @param {number} index Index which key should be increased
51+
* @param {number} index Index which key should be changed
4452
* @param {number} value New value of the key
4553
* @returns {number} parent The new position of the element
4654
*/
47-
MaxHeap.prototype.increaseKey = function (index, value) {
55+
Heap.prototype.changeKey = function (index, value) {
4856
var elem = this._heap[index],
4957
parent = Math.floor(index / 2),
5058
temp;
51-
if (elem && elem <= value) {
52-
while (parent >= 0 && elem > this._heap[parent]) {
59+
if (elem !== undefined) {
60+
while (parent >= 0 && this._cmp(elem, this._heap[parent]) > 0) {
5361
temp = this._heap[parent];
5462
this._heap[parent] = elem;
5563
this._heap[index] = temp;
@@ -67,34 +75,35 @@ MaxHeap.prototype.increaseKey = function (index, value) {
6775
* @param {number} value The new value which will be inserted
6876
* @returns {number} The index of the inserted value
6977
*/
70-
MaxHeap.prototype.add = function (value) {
78+
Heap.prototype.add = function (value) {
7179
this._heap.push(value);
72-
return this.increaseKey(this._heap.length - 1, value);
80+
return this.changeKey(this._heap.length - 1, value);
7381
}
7482

7583
/**
7684
* Gets the current value which is on the top of the heap. Complexity O(1).
7785
*
7886
* @public
79-
* returns {numner} The current largest value which is on the top of the heap
87+
* returns {numner} The current top value.
8088
*/
81-
MaxHeap.prototype.max = function () {
89+
Heap.prototype.top = function () {
8290
return this._heap[0];
8391
}
8492

8593
/**
86-
* Remove and return the current maximum value which is on the top of the heap.
94+
* Removes and returns the current extremum value which is on the top of the heap.
8795
* Complexity O(log n).
8896
*
8997
* @public
90-
* @returns {number} max Extracted value
98+
* @returns {number} The extremum value
9199
*/
92-
MaxHeap.prototype.extractMax = function () {
100+
Heap.prototype.extract = function () {
93101
if (!this._heap.length)
94102
throw new 'The heap is already empty!';
95103

96-
var max = this._heap.shift();
104+
var extr = this._heap.shift();
97105
this._heapify(0);
98-
return max;
106+
return extr;
99107
}
100108

109+
exports.Heap = Heap;

‎src/graphs/dijkstra.js‎

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * *
2+
3+
A sample distance matrix
4+
5+
var graph = [[NaN, 7, 9, NaN, NaN, 16],
6+
[7, NaN, 10, 15, NaN, NaN],
7+
[9, 10, NaN, 11, NaN, 2],
8+
[NaN, 15, 11, NaN, 6, NaN],
9+
[NaN, NaN, NaN, 6, NaN, 9],
10+
[16, NaN, 2, NaN, 9, NaN]];
11+
12+
* * * * * * * * * * * * * * * * * * * * * * * */
13+
14+
15+
/**
16+
* Dijstra's shortest path algorithm.
17+
* For the implementation is not used the most suitable data structure (Fibonacci heap)
18+
* but the binary heap gives also good results. The implementation bellow finds
19+
* the minimum distance between two given nodes using a distance matrix.
20+
*/
21+
var dijstra = function () {
22+
23+
var Heap = require('../data-structures/heap.js').Heap,
24+
current,
25+
visited,
26+
distance,
27+
unvisited;
28+
29+
30+
/**
31+
* Creates a new node instance
32+
*
33+
* @constructor
34+
* @private
35+
* @param {number} id The id of the node
36+
* @param {number} distance The distance from the beginning
37+
*/
38+
function Node(id, distance) {
39+
this.node = id;
40+
this.distance = distance;
41+
}
42+
43+
/**
44+
* Compares the distances between two nodes.
45+
*
46+
* @private
47+
* @param {object} a A node
48+
* @param {object} b A graph node
49+
* @returns {number} The
50+
*/
51+
function compareNodesDistance(a, b) {
52+
return b.distance - a.distance;
53+
}
54+
55+
/**
56+
* Initialize all variables used for the algorithm
57+
*
58+
* @private
59+
* @param {number} src A start node
60+
*/
61+
function init(src) {
62+
var currentTemp;
63+
current = {};
64+
visited = [];
65+
distance = [];
66+
unvisited = new Heap(compareNodesDistance);
67+
for (var i = 0; i < graph.length; i += 1) {
68+
currentTemp = new Node();
69+
if (src === i) {
70+
currentTemp.distance = 0;
71+
} else {
72+
currentTemp.distance = Infinity;
73+
}
74+
currentTemp.node = i;
75+
visited[i] = false;
76+
distance[i] = currentTemp;
77+
unvisited.add(currentTemp);
78+
}
79+
current.node = src;
80+
current.distance = 0;
81+
}
82+
83+
/**
84+
* Dijkstra's shortest path algorithm
85+
*
86+
* @public
87+
* @param {number} src Source node
88+
* @param {number} dest Destination node
89+
* @param {array} graph A distance matrix of the graph
90+
* @returns {number} The shortest distance between the nodes
91+
*/
92+
return function (src, dest, graph) {
93+
var tempDistance = 0;
94+
init(src);
95+
while (current.node != dest && current.distance != Infinity) {
96+
for (var i = 0; i < graph.length; i += 1) {
97+
if (current.node !== i && //if it's not the current node
98+
!visited[i] && //and if we haven't visited this node
99+
!isNaN(graph[i][current.node])) { //and this node is sibling of the current...
100+
101+
tempDistance = current.distance + graph[i][current.node];
102+
if (tempDistance < distance[i].distance) {
103+
distance[i].distance = tempDistance;
104+
}
105+
}
106+
}
107+
visited[current.node] = true;
108+
current = unvisited.extract();
109+
}
110+
return distance[dest].distance;
111+
};
112+
}();

0 commit comments

Comments
 (0)