-
Notifications
You must be signed in to change notification settings - Fork 20
/
heapqueue.js
103 lines (89 loc) · 2.88 KB
/
heapqueue.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
/*
This implementation is very loosely based off js-priority-queue
by Adam Hooper from https://github.com/adamhooper/js-priority-queue
The js-priority-queue implementation seemed a teensy bit bloated
with its require.js dependency and multiple storage strategies
when all but one were strongly discouraged. So here is a kind of
condensed version of the functionality with only the features that
I particularly needed.
Using it is pretty simple, you just create an instance of HeapQueue
while optionally specifying a comparator as the argument:
var heapq = new HeapQueue()
var customq = new HeapQueue(function(a, b){
// if b > a, return negative
// means that it spits out the smallest item first
return a - b
})
Note that in this case, the default comparator is identical to
the comparator which is used explicitly in the second queue.
Once you've initialized the heapqueue, you can plop some new
elements into the queue with the push method (vaguely reminiscent
of typical javascript arays)
heapq.push(42);
heapq.push("kitten");
The push method returns the new number of elements of the queue.
You can push anything you'd like onto the queue, so long as your
comparator function is capable of handling it. The default
comparator is really stupid so it won't be able to handle anything
other than an number by default.
You can preview the smallest item by using peek.
heapq.push(-9999)
heapq.peek() ==> -9999
The useful complement to to the push method is the pop method,
which returns the smallest item and then removes it from the
queue.
heapq.push(1)
heapq.push(2)
heapq.push(3)
heapq.pop() ==> 1
heapq.pop() ==> 2
heapq.pop() ==> 3
*/
function HeapQueue(cmp){
this.cmp = (cmp || function(a, b){ return a - b });
this.length = 0;
this.data = []
}
HeapQueue.prototype.peek = function(){
return this.data[0]
}
HeapQueue.prototype.push = function(value){
this.data.push(value);
var pos = this.data.length - 1,
parent, x;
while(pos > 0){
parent = (pos - 1) >>> 1;
if(this.cmp(this.data[pos], this.data[parent]) < 0){
x = this.data[parent]
this.data[parent] = this.data[pos];
this.data[pos] = x;
pos = parent;
}else break;
}
return ++this.length;
}
HeapQueue.prototype.pop = function(){
var ret = this.data[0],
last_val = this.data.pop();
this.length--;
if(this.data.length > 0){
this.data[0] = last_val;
var pos = 0,
last = this.data.length - 1,
left, right, minIndex, x;
while(1){
left = (pos << 1) + 1;
right = left + 1;
minIndex = pos;
if(left <= last && this.cmp(this.data[left], this.data[minIndex]) < 0) minIndex = left;
if(right <= last && this.cmp(this.data[right], this.data[minIndex]) < 0) minIndex = right;
if(minIndex !== pos){
x = this.data[minIndex]
this.data[minIndex] = this.data[pos]
this.data[pos] = x;
pos = minIndex
}else break;
}
}
return ret
}