-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
/
Copy pathMaxHeapAdhoc.js
107 lines (87 loc) · 2.77 KB
/
MaxHeapAdhoc.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
/**
* The minimalistic (ad hoc) version of a MaxHeap data structure that doesn't have
* external dependencies and that is easy to copy-paste and use during the
* coding interview if allowed by the interviewer (since many data
* structures in JS are missing).
*/
class MaxHeapAdhoc {
constructor(heap = []) {
this.heap = [];
// Use an arrow function to maintain context for 'this'.
heap.forEach(num => this.add(num));
}
add(num) {
this.heap.push(num);
this.heapifyUp();
}
peek() {
return this.isEmpty() ? undefined : this.heap[0];
}
poll() {
if (this.isEmpty()) return undefined;
const top = this.heap[0];
const last = this.heap.pop(); // Remove the last element to replace the top
if (!this.isEmpty()) {
this.heap[0] = last; // Move the last element to the root
this.heapifyDown(); // Re-establish the heap property
}
return top;
}
isEmpty() {
return this.heap.length === 0;
}
toString() {
return this.heap.join(',');
}
heapifyUp() {
let nodeIndex = this.heap.length - 1;
while (nodeIndex > 0) {
const parentIndex = this.getParentIndex(nodeIndex);
if (this.heap[parentIndex] >= this.heap[nodeIndex]) break;
this.swap(parentIndex, nodeIndex);
nodeIndex = parentIndex;
}
}
heapifyDown() {
let nodeIndex = 0;
while (this.hasLeftChild(nodeIndex)) {
const leftIndex = this.getLeftChildIndex(nodeIndex);
const rightIndex = this.getRightChildIndex(nodeIndex);
let largerChildIndex = leftIndex;
// Check if the right child exists and is greater than the left child
if (this.hasRightChild(nodeIndex) && this.rightChild(nodeIndex) > this.leftChild(nodeIndex)) {
largerChildIndex = rightIndex;
}
// If the current node is greater than the largest child, break
if (this.heap[nodeIndex] >= this.heap[largerChildIndex]) break;
// Swap with the larger child
this.swap(nodeIndex, largerChildIndex);
nodeIndex = largerChildIndex;
}
}
getLeftChildIndex(parentIndex) {
return (2 * parentIndex) + 1;
}
getRightChildIndex(parentIndex) {
return (2 * parentIndex) + 2;
}
getParentIndex(childIndex) {
return Math.floor((childIndex - 1) / 2);
}
hasLeftChild(parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heap.length;
}
hasRightChild(parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heap.length;
}
leftChild(parentIndex) {
return this.heap[this.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heap[this.getRightChildIndex(parentIndex)];
}
swap(indexOne, indexTwo) {
[this.heap[indexOne], this.heap[indexTwo]] = [this.heap[indexTwo], this.heap[indexOne]];
}
}
export default MaxHeapAdhoc;