Skip to content

Commit a7956bd

Browse files
authored
Merge pull request knaxus#155 from knaxus/heaps
Heaps
2 parents 0561ee8 + 6a5e13a commit a7956bd

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const MaxHeap = require('.');
2+
3+
describe('MaxHeap', () => {
4+
it('Should be a class', () => {
5+
expect(typeof MaxHeap.prototype.constructor).toEqual('function');
6+
});
7+
8+
const mh = new MaxHeap();
9+
10+
beforeEach(() => {
11+
mh.destroy();
12+
});
13+
14+
it('Should create an instance of MaxHeap', () => {
15+
expect(mh instanceof MaxHeap).toEqual(true);
16+
});
17+
18+
it('Should add an element to the MaxHeap', () => {
19+
mh.add(10);
20+
expect(mh.getMax()).toEqual(10);
21+
});
22+
23+
it('Should keep the largest element at the root', () => {
24+
[12, 5, 34].forEach(el => mh.add(el));
25+
expect(mh.getMax()).toEqual(34);
26+
});
27+
28+
it('Should retain Heap properties after removal of an element', () => {
29+
[12, 45, 1, 34].forEach(el => mh.add(el));
30+
expect(mh.getMax()).toEqual(45);
31+
mh.remove();
32+
expect(mh.getMax()).toEqual(34);
33+
});
34+
35+
it('Should return `null` when heap is empty', () => {
36+
[1, 34].forEach(el => mh.add(el));
37+
expect(mh.getMax()).toEqual(34);
38+
mh.remove();
39+
mh.remove();
40+
expect(mh.getMax()).toEqual(null);
41+
});
42+
43+
it('Should return the elelment value on `remove()`', () => {
44+
[1, 34].forEach(el => mh.add(el));
45+
expect(mh.getMax()).toEqual(34);
46+
expect(mh.remove()).toEqual(34);
47+
expect(mh.remove()).toEqual(1);
48+
expect(mh.getMax()).toEqual(null);
49+
});
50+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
class MaxHeap {
2+
constructor() {
3+
this.heap = [];
4+
}
5+
6+
add(element) {
7+
this.heap.push(element);
8+
// check for the parent element & swap if required
9+
// eslint-disable-next-line no-underscore-dangle
10+
this.__traverseUpAndSwap(this.heap.length - 1);
11+
}
12+
13+
getMax() {
14+
return this.heap[0] || null;
15+
}
16+
17+
remove() {
18+
// return the element at the root
19+
const max = this.heap[0] || null;
20+
if (this.heap.length > 1) {
21+
// move the leaf to the root
22+
this.heap[0] = this.heap[this.heap.length - 1];
23+
this.heap.splice(this.heap.length - 1, 1);
24+
// restore the heapify property
25+
// eslint-disable-next-line no-underscore-dangle
26+
this.__heapify(0);
27+
return max;
28+
}
29+
30+
if (this.heap.length === 1) {
31+
this.heap.splice(this.heap.length - 1, 1);
32+
return max;
33+
}
34+
35+
return max;
36+
}
37+
38+
__heapify(index) {
39+
const left = index * 2;
40+
const right = index * 2 + 1;
41+
let largest = index;
42+
43+
if (this.heap.length > left && this.heap[largest] < this.heap[left]) {
44+
largest = left;
45+
}
46+
47+
if (this.heap.length > right && this.heap[largest] < this.heap[right]) {
48+
largest = right;
49+
}
50+
51+
if (largest !== index) {
52+
const temp = this.heap[largest];
53+
this.heap[largest] = this.heap[index];
54+
this.heap[index] = temp;
55+
// eslint-disable-next-line no-underscore-dangle
56+
this.__heapify(largest);
57+
}
58+
}
59+
60+
__traverseUpAndSwap(index) {
61+
if (index <= 0) return;
62+
const parent = Math.floor(index / 2);
63+
64+
if (this.heap[parent] < this.heap[index]) {
65+
const temp = this.heap[parent];
66+
this.heap[parent] = this.heap[index];
67+
this.heap[index] = temp;
68+
// eslint-disable-next-line no-underscore-dangle
69+
this.__traverseUpAndSwap(parent);
70+
}
71+
}
72+
73+
destroy() {
74+
this.heap = [];
75+
}
76+
}
77+
78+
module.exports = MaxHeap;

0 commit comments

Comments
 (0)