Skip to content

Commit 827177f

Browse files
committed
feat(heap): add error handling for heaps
BREAKING CHANGE: size is now an attribute rather than a method. Similar to the built-in Map.size and Set.size
1 parent 3a2a24f commit 827177f

File tree

4 files changed

+41
-29
lines changed

4 files changed

+41
-29
lines changed

src/data-structures/heaps/heap.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
classHeap{
99
constructor(comparator=(a,b)=>a-b){
1010
this.array=[];
11-
this.comparator=(i1,i2)=>comparator(this.array[i1],this.array[i2]);
11+
this.comparator=(i1,i2)=>{
12+
constvalue=comparator(this.array[i1],this.array[i2]);
13+
if(Number.isNaN(value)){thrownewError(`Comparator should evaluate to a number. Got ${value} when comparing ${this.array[i1]} with ${this.array[i2]}`);}
14+
returnvalue;
15+
};
1216
}
1317

1418
/**
@@ -34,8 +38,8 @@ class Heap {
3438
* @runtime O(log n)
3539
*/
3640
remove(index=0){
37-
if(!this.size())returnnull;
38-
this.swap(index,this.size()-1);// swap with last
41+
if(!this.size)returnnull;
42+
this.swap(index,this.size-1);// swap with last
3943
constvalue=this.array.pop();// remove element
4044
this.bubbleDown(index);
4145
returnvalue;
@@ -45,7 +49,7 @@ class Heap {
4549
* Returns the number of elements in this collection.
4650
* @runtime O(1)
4751
*/
48-
size(){
52+
getsize(){
4953
returnthis.array.length;
5054
}
5155

@@ -54,7 +58,7 @@ class Heap {
5458
* @runtime O(log n)
5559
*/
5660
bubbleUp(){
57-
letindex=this.size()-1;
61+
letindex=this.size-1;
5862
constparent=(i)=>Math.ceil(i/2-1);
5963
while(parent(index)>=0&&this.comparator(parent(index),index)>0){
6064
this.swap(parent(index),index);
@@ -70,18 +74,18 @@ class Heap {
7074
letcurr=index;
7175
constleft=(i)=>2*i+1;
7276
constright=(i)=>2*i+2;
73-
constgetTopChild=(i)=>(right(i)<this.size()
77+
constgetTopChild=(i)=>(right(i)<this.size
7478
&&this.comparator(left(i),right(i))>0 ? right(i) : left(i));
7579

76-
while(left(curr)<this.size()&&this.comparator(curr,getTopChild(curr))>0){
80+
while(left(curr)<this.size&&this.comparator(curr,getTopChild(curr))>0){
7781
constnext=getTopChild(curr);
7882
this.swap(curr,next);
7983
curr=next;
8084
}
8185
}
8286

8387
/**
84-
* "Private": Swap elements on the heap
88+
* Swap elements on the heap
8589
* @runtime O(1)
8690
* @param {number} i1 index 1
8791
* @param {number} i2 index 2

src/data-structures/heaps/heap.spec.js

+21-13
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ const PriorityQueue = require('./priority-queue');
33
constMaxHeap=require('./max-heap');
44
constMinHeap=require('./min-heap');
55

6-
[[Heap],[PriorityQueue],[MinHeap]].forEach(([DS,arg])=>{
7-
describe('Min-Heap (Priority Queue)',()=>{
6+
[
7+
[Heap],
8+
[PriorityQueue,[],(a,b)=>a-b],
9+
[MinHeap],
10+
].forEach(([DS, ...arg])=>{
11+
describe('Min-Heap and Priority Queue',()=>{
812
letheap;
913

1014
beforeEach(()=>{
11-
heap=newDS(arg);
15+
heap=newDS(...arg);
1216
});
1317

1418
describe('#contructor',()=>{
@@ -21,7 +25,7 @@ const MinHeap = require('./min-heap');
2125
it('should add an element',()=>{
2226
expect(heap.add(1)).toBe(undefined);
2327
expect(heap.array).toEqual([1]);
24-
expect(heap.size()).toBe(1);
28+
expect(heap.size).toBe(1);
2529
});
2630

2731
it('should keep things in order',()=>{
@@ -31,7 +35,7 @@ const MinHeap = require('./min-heap');
3135
expect(heap.array[0]).toEqual(2);
3236
heap.add(1);
3337
expect(heap.array[0]).toEqual(1);
34-
expect(heap.size()).toEqual(3);
38+
expect(heap.size).toEqual(3);
3539
});
3640
});
3741

@@ -40,7 +44,7 @@ const MinHeap = require('./min-heap');
4044
heap.add(1);
4145
heap.add(0);
4246
expect(heap.remove()).toBe(0);
43-
expect(heap.size()).toBe(1);
47+
expect(heap.size).toBe(1);
4448
expect(heap.array).toEqual([1]);
4549
});
4650

@@ -70,19 +74,23 @@ const MinHeap = require('./min-heap');
7074
expect(heap.remove()).toEqual(1);
7175
expect(heap.remove()).toEqual(2);
7276
expect(heap.remove()).toEqual(3);
73-
expect(heap.size()).toBe(0);
77+
expect(heap.size).toBe(0);
7478
});
7579
});
7680
});
7781
});
7882
});
7983

80-
[[Heap,(a,b)=>b-a],[PriorityQueue,(a,b)=>b-a],[MaxHeap]].forEach(([DS,arg])=>{
84+
[
85+
[Heap,(a,b)=>b-a],
86+
[PriorityQueue,[],(a,b)=>b-a],
87+
[MaxHeap],
88+
].forEach(([DS, ...arg])=>{
8189
describe('Max-Heap (Priority Queue)',()=>{
8290
letheap;
8391

8492
beforeEach(()=>{
85-
heap=newDS(arg);
93+
heap=newDS(...arg);
8694
});
8795

8896
describe('#contructor',()=>{
@@ -95,7 +103,7 @@ const MinHeap = require('./min-heap');
95103
it('should add an element',()=>{
96104
expect(heap.add(1)).toBe(undefined);
97105
expect(heap.array).toEqual([1]);
98-
expect(heap.size()).toBe(1);
106+
expect(heap.size).toBe(1);
99107
});
100108

101109
it('should keep things in order',()=>{
@@ -105,7 +113,7 @@ const MinHeap = require('./min-heap');
105113
expect(heap.array[0]).toEqual(2);
106114
heap.add(3);
107115
expect(heap.array[0]).toEqual(3);
108-
expect(heap.size()).toEqual(3);
116+
expect(heap.size).toEqual(3);
109117
});
110118
});
111119

@@ -114,7 +122,7 @@ const MinHeap = require('./min-heap');
114122
heap.add(1);
115123
heap.add(0);
116124
expect(heap.remove()).toBe(1);
117-
expect(heap.size()).toBe(1);
125+
expect(heap.size).toBe(1);
118126
expect(heap.array).toEqual([0]);
119127
});
120128

@@ -156,7 +164,7 @@ const MinHeap = require('./min-heap');
156164
expect(heap.remove()).toEqual(2);
157165
expect(heap.remove()).toEqual(1);
158166
expect(heap.remove()).toEqual(0);
159-
expect(heap.size()).toBe(0);
167+
expect(heap.size).toBe(0);
160168
});
161169
});
162170
});

src/data-structures/heaps/median-heap.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class MedianHeap {
3030
}
3131

3232
// rebalance if the sizes of the heaps differ by more than one element
33-
if(Math.abs(this.min.size()-this.max.size())>1){
33+
if(Math.abs(this.min.size-this.max.size)>1){
3434
// extract the min/max from the heap with more elements and insert it into the other heap.
35-
if(this.min.size()>this.max.size()){
35+
if(this.min.size>this.max.size){
3636
this.max.add(this.min.remove());
3737
}else{
3838
this.min.add(this.max.remove());
@@ -47,12 +47,12 @@ class MedianHeap {
4747
findMedian(){
4848
letmedian;
4949

50-
if(this.max.size()===this.min.size()){
50+
if(this.max.size===this.min.size){
5151
// When both heaps contain the same number of elements,
5252
// the total number of elements is even.
5353
// The median is the mean of the two middle elements.
5454
median=(this.max.peek()+this.min.peek())/2;
55-
}elseif(this.max.size()>this.min.size()){
55+
}elseif(this.max.size>this.min.size){
5656
// when the max-heap contains one more element than the min-heap,
5757
// the median is in the top of the max-heap.
5858
median=this.max.peek();
@@ -67,8 +67,8 @@ class MedianHeap {
6767
/**
6868
* Return size of the heap.
6969
*/
70-
size(){
71-
returnthis.min.size()+this.max.size();
70+
getsize(){
71+
returnthis.min.size+this.max.size;
7272
}
7373
}
7474

src/data-structures/heaps/median-heap.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ describe('Median Heap', () => {
1010
describe('#add',()=>{
1111
it('should work',()=>{
1212
expect(medianHeap.add(1)).toEqual(undefined);
13-
expect(medianHeap.size()).toEqual(1);
13+
expect(medianHeap.size).toEqual(1);
1414
});
1515

1616
it('should work',()=>{
1717
expect(medianHeap.add(1)).toEqual(undefined);
1818
expect(medianHeap.add(1)).toEqual(undefined);
19-
expect(medianHeap.size()).toEqual(2);
19+
expect(medianHeap.size).toEqual(2);
2020
});
2121
});
2222

0 commit comments

Comments
 (0)
close