@@ -14,31 +14,31 @@ export default class MinHeap {
14
14
* @param {number } parentIndex
15
15
* @return {number }
16
16
*/
17
- static getLeftChildIndex ( parentIndex ) {
17
+ getLeftChildIndex ( parentIndex ) {
18
18
return ( 2 * parentIndex ) + 1 ;
19
19
}
20
20
21
21
/**
22
22
* @param {number } parentIndex
23
23
* @return {number }
24
24
*/
25
- static getRightChildIndex ( parentIndex ) {
25
+ getRightChildIndex ( parentIndex ) {
26
26
return ( 2 * parentIndex ) + 2 ;
27
27
}
28
28
29
29
/**
30
30
* @param {number } childIndex
31
31
* @return {number }
32
32
*/
33
- static getParentIndex ( childIndex ) {
33
+ getParentIndex ( childIndex ) {
34
34
return Math . floor ( ( childIndex - 1 ) / 2 ) ;
35
35
}
36
36
37
37
/**
38
38
* @param {number } childIndex
39
39
* @return {boolean }
40
40
*/
41
- static hasParent ( childIndex ) {
41
+ hasParent ( childIndex ) {
42
42
return this . getParentIndex ( childIndex ) >= 0 ;
43
43
}
44
44
@@ -47,39 +47,39 @@ export default class MinHeap {
47
47
* @return {boolean }
48
48
*/
49
49
hasLeftChild ( parentIndex ) {
50
- return MinHeap . getLeftChildIndex ( parentIndex ) < this . heapContainer . length ;
50
+ return this . getLeftChildIndex ( parentIndex ) < this . heapContainer . length ;
51
51
}
52
52
53
53
/**
54
54
* @param {number } parentIndex
55
55
* @return {boolean }
56
56
*/
57
57
hasRightChild ( parentIndex ) {
58
- return MinHeap . getRightChildIndex ( parentIndex ) < this . heapContainer . length ;
58
+ return this . getRightChildIndex ( parentIndex ) < this . heapContainer . length ;
59
59
}
60
60
61
61
/**
62
62
* @param {number } parentIndex
63
63
* @return {* }
64
64
*/
65
65
leftChild ( parentIndex ) {
66
- return this . heapContainer [ MinHeap . getLeftChildIndex ( parentIndex ) ] ;
66
+ return this . heapContainer [ this . getLeftChildIndex ( parentIndex ) ] ;
67
67
}
68
68
69
69
/**
70
70
* @param {number } parentIndex
71
71
* @return {* }
72
72
*/
73
73
rightChild ( parentIndex ) {
74
- return this . heapContainer [ MinHeap . getRightChildIndex ( parentIndex ) ] ;
74
+ return this . heapContainer [ this . getRightChildIndex ( parentIndex ) ] ;
75
75
}
76
76
77
77
/**
78
78
* @param {number } childIndex
79
79
* @return {* }
80
80
*/
81
81
parent ( childIndex ) {
82
- return this . heapContainer [ MinHeap . getParentIndex ( childIndex ) ] ;
82
+ return this . heapContainer [ this . getParentIndex ( childIndex ) ] ;
83
83
}
84
84
85
85
/**
@@ -126,17 +126,63 @@ export default class MinHeap {
126
126
127
127
/**
128
128
* @param {* } item
129
+ * @return {MinHeap }
129
130
*/
130
131
add ( item ) {
131
132
this . heapContainer . push ( item ) ;
132
133
this . heapifyUp ( ) ;
134
+ return this ;
135
+ }
136
+
137
+ /**
138
+ * @param {* } item
139
+ * @return {MinHeap }
140
+ */
141
+ remove ( item ) {
142
+ // Find number of items to remove.
143
+ const numberOfItemsToRemove = this . find ( item ) . length ;
144
+
145
+ for ( let iteration = 0 ; iteration < numberOfItemsToRemove ; iteration += 1 ) {
146
+ // We need to find item index to remove each time after removal since
147
+ // indices are being change after each heapify process.
148
+ const indexToRemove = this . find ( item ) . pop ( ) ;
149
+
150
+ // If we need to remove last child in the heap then just remove it.
151
+ // There is no need to heapify the heap afterwards.
152
+ if ( indexToRemove === ( this . heapContainer . length - 1 ) ) {
153
+ this . heapContainer . pop ( ) ;
154
+ } else {
155
+ // Move last element in heap to the vacant (removed) position.
156
+ this . heapContainer [ indexToRemove ] = this . heapContainer . pop ( ) ;
157
+
158
+ // Get parent.
159
+ const parentItem = this . hasParent ( indexToRemove ) ? this . parent ( indexToRemove ) : null ;
160
+ const leftChild = this . hasLeftChild ( indexToRemove ) ? this . leftChild ( indexToRemove ) : null ;
161
+
162
+ // If there is no parent or parent is less then node to delete then heapify down.
163
+ // Otherwise heapify up.
164
+ if (
165
+ leftChild !== null &&
166
+ (
167
+ parentItem === null ||
168
+ this . compare . lessThen ( parentItem , this . heapContainer [ indexToRemove ] )
169
+ )
170
+ ) {
171
+ this . heapifyDown ( indexToRemove ) ;
172
+ } else {
173
+ this . heapifyUp ( indexToRemove ) ;
174
+ }
175
+ }
176
+ }
177
+
178
+ return this ;
133
179
}
134
180
135
181
/**
136
182
* @param {* } item
137
183
* @return {Number[] }
138
184
*/
139
- findItem ( item ) {
185
+ find ( item ) {
140
186
const foundItemIndices = [ ] ;
141
187
142
188
for ( let itemIndex = 0 ; itemIndex < this . heapContainer . length ; itemIndex += 1 ) {
@@ -148,35 +194,41 @@ export default class MinHeap {
148
194
return foundItemIndices ;
149
195
}
150
196
151
- heapifyUp ( ) {
197
+ /**
198
+ * @param {number } [customStartIndex]
199
+ */
200
+ heapifyUp ( customStartIndex ) {
152
201
// Take last element (last in array or the bottom left in a tree) in
153
202
// a heap container and lift him up until we find the parent element
154
203
// that is less then the current new one.
155
- let currentIndex = this . heapContainer . length - 1 ;
204
+ let currentIndex = customStartIndex || this . heapContainer . length - 1 ;
156
205
157
206
while (
158
- MinHeap . hasParent ( currentIndex ) &&
207
+ this . hasParent ( currentIndex ) &&
159
208
this . compare . lessThen ( this . heapContainer [ currentIndex ] , this . parent ( currentIndex ) )
160
209
) {
161
- this . swap ( currentIndex , MinHeap . getParentIndex ( currentIndex ) ) ;
162
- currentIndex = MinHeap . getParentIndex ( currentIndex ) ;
210
+ this . swap ( currentIndex , this . getParentIndex ( currentIndex ) ) ;
211
+ currentIndex = this . getParentIndex ( currentIndex ) ;
163
212
}
164
213
}
165
214
166
- heapifyDown ( ) {
215
+ /**
216
+ * @param {number } [customStartIndex]
217
+ */
218
+ heapifyDown ( customStartIndex ) {
167
219
// Compare the root element to its children and swap root with the smallest
168
220
// of children. Do the same for next children after swap.
169
- let currentIndex = 0 ;
170
- let nextIndex = 0 ;
221
+ let currentIndex = customStartIndex || 0 ;
222
+ let nextIndex = null ;
171
223
172
224
while ( this . hasLeftChild ( currentIndex ) ) {
173
225
if (
174
226
this . hasRightChild ( currentIndex ) &&
175
227
this . compare . lessThen ( this . rightChild ( currentIndex ) , this . leftChild ( currentIndex ) )
176
228
) {
177
- nextIndex = MinHeap . getRightChildIndex ( currentIndex ) ;
229
+ nextIndex = this . getRightChildIndex ( currentIndex ) ;
178
230
} else {
179
- nextIndex = MinHeap . getLeftChildIndex ( currentIndex ) ;
231
+ nextIndex = this . getLeftChildIndex ( currentIndex ) ;
180
232
}
181
233
182
234
if ( this . compare . lessThen ( this . heapContainer [ currentIndex ] , this . heapContainer [ nextIndex ] ) ) {
0 commit comments