forked from trekhleb/javascript-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMinHeap.js
More file actions
137 lines (109 loc) · 3.28 KB
/
MinHeap.js
File metadata and controls
137 lines (109 loc) · 3.28 KB
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
export default class MinHeap {
constructor() {
// Array representation of the heap.
this.heapContainer = [];
}
static getLeftChildIndex(parentIndex) {
return (2 * parentIndex) + 1;
}
static getRightChildIndex(parentIndex) {
return (2 * parentIndex) + 2;
}
static getParentIndex(childIndex) {
return Math.floor((childIndex - 1) / 2);
}
static hasParent(childIndex) {
return this.getParentIndex(childIndex) >= 0;
}
hasLeftChild(parentIndex) {
return MinHeap.getLeftChildIndex(parentIndex) < this.heapContainer.length;
}
hasRightChild(parentIndex) {
return MinHeap.getRightChildIndex(parentIndex) < this.heapContainer.length;
}
leftChild(parentIndex) {
return this.heapContainer[MinHeap.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heapContainer[MinHeap.getRightChildIndex(parentIndex)];
}
parent(childIndex) {
return this.heapContainer[MinHeap.getParentIndex(childIndex)];
}
swap(indexOne, indexTwo) {
const tmp = this.heapContainer[indexTwo];
this.heapContainer[indexTwo] = this.heapContainer[indexOne];
this.heapContainer[indexOne] = tmp;
}
peek() {
if (this.heapContainer.length === 0) {
return null;
}
return this.heapContainer[0];
}
poll() {
if (this.heapContainer.length === 0) {
return null;
}
if (this.heapContainer.length === 1) {
return this.heapContainer.pop();
}
const item = this.heapContainer[0];
// Move the last element from the end to the head.
this.heapContainer[0] = this.heapContainer.pop();
this.heapifyDown();
return item;
}
add(item) {
this.heapContainer.push(item);
this.heapifyUp();
}
heapifyUp() {
// Take last element (last in array or the bottom left in a tree) in
// a heap container and lift him up until we find the parent element
// that is less then the current new one.
let currentIndex = this.heapContainer.length - 1;
while (
MinHeap.hasParent(currentIndex) &&
this.lessThen(this.heapContainer[currentIndex], this.parent(currentIndex))
) {
this.swap(currentIndex, MinHeap.getParentIndex(currentIndex));
currentIndex = MinHeap.getParentIndex(currentIndex);
}
}
heapifyDown() {
// Compare the root element to its children and swap root with the smallest
// of children. Do the same for next children after swap.
let currentIndex = 0;
let nextIndex = 0;
while (this.hasLeftChild(currentIndex)) {
if (
this.hasRightChild(currentIndex) &&
this.lessThen(this.rightChild(currentIndex), this.leftChild(currentIndex))
) {
nextIndex = MinHeap.getRightChildIndex(currentIndex);
} else {
nextIndex = MinHeap.getLeftChildIndex(currentIndex);
}
if (this.lessThen(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) {
break;
}
this.swap(currentIndex, nextIndex);
currentIndex = nextIndex;
}
}
toString() {
return this.heapContainer.toString();
}
compare(a, b) {
if (a === b) {
return 0;
}
// Min heap may be converted to max heap by simply changing this line to:
// a > b ? -1 : 1
return a < b ? -1 : 1;
}
lessThen(a, b) {
return this.compare(a, b) === -1;
}
}