forked from janogonzalez/priorityqueuejs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
149 lines (129 loc) · 3.64 KB
/
index.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
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
144
145
146
147
148
149
/**
* Given comparator and array, it creates a BinaryHeap instance determined by the comparator
* order filled with the array elements.
*
* The comparator function must receive two element arguments and return:
* - a positive number when first argument is greater than second
* - 0 when first argument is equal to the second
* - negative number when first argument is lower than the second
*
* @api public
* @param {Function} comparator - function which compares elements.
* @param {Array} [array=[]] - array of elements to insert in heap.
* or comparator function if array does not passed.
* @returns {BinaryHeap} create instance of binary heap class.
* @complexity O(N) such that N = array.length
*/
function BinaryHeap(comparator, array = []) {
const size = array.length
this._comparator = comparator
this._elements = [].concat(array)
for (let i = Math.floor(0.5 * size) - 1; i >= 0; --i) {
sink.call(this, i, size)
}
}
const BinaryHeapProto = BinaryHeap.prototype
/**
* Returns the size of the binary heap.
*
* @api public
* @returns {Number} size of heap
* @complexity O(1)
*/
Object.defineProperty(BinaryHeapProto, 'size', {
get() {
return this._elements.length
}
})
/**
* Peeks at the top element of the binary heap.
*
* @api public
* @returns {*} element of binary heap
* @complexity O(1)
*/
BinaryHeapProto.top = function() {
return this._elements[0]
}
/**
* Gets the top element of the binary heap.
*
* @api public
* @returns {*} element of binary heap
* @complexity O(log(N)) such that N === this.size
*/
BinaryHeapProto.pop = function() {
const first = this.top()
const last = this._elements.pop()
const size = this.size
if (size > 0) {
this._elements[0] = last
sink.call(this, 0, size)
}
return first
}
/**
* Push the `element` at the binary heap and returns its new size.
*
* @api public
* @param {*} element of binary heap
* @returns {Number} new size of heap
* @complexity O(log(N)) such that N === this.size
*/
BinaryHeapProto.push = function(element) {
const size = this._elements.push(element)
let current = size - 1
while (current > 0) {
const parent = Math.floor((current - 1) / 2)
if (_compare.call(this, current, parent) <= 0) {
break
}
_swap.call(this, parent, current)
current = parent
}
return size
}
/**
* Compares the values at position `a` and `b` in the binary heap using its
* comparator function.
*
* @api private
* @param {Number} a - position of first value
* @param {Number} b - position of second value
* @returns {Number} - number such that sign indicates the status of comparison
*/
function _compare(a, b) {
return this._comparator(this._elements[a], this._elements[b])
}
/**
* Swaps the values at position `a` and `b` in the binary heap.
*
* @api private
* @param {Number} a - position of first value
* @param {Number} b - position of second value
* @returns {undefined}
*/
function _swap(a, b) {
const aux = this._elements[a]
this._elements[a] = this._elements[b]
this._elements[b] = aux
}
function sink(current, size) {
while (current < size) {
let largest = current
const left = (2 * current) + 1
const right = left + 1
if (left < size && _compare.call(this, left, largest) >= 0) {
largest = left
}
if (right < size && _compare.call(this, right, largest) >= 0) {
largest = right
}
if (largest === current) {
break
}
_swap.call(this, largest, current)
current = largest
}
}
module.exports = BinaryHeap