This repository has been archived by the owner on Mar 30, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BinaryMaxHeap.java
333 lines (295 loc) · 8.52 KB
/
BinaryMaxHeap.java
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
package assign10;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Creates a Binary Max Heap implementing a PriorityQueue interface
*
* @author Paul Nuffer and Nils Streedain
*
* @param <E> - the generic type of element stored in the BinaryMaxHeap
*/
public class BinaryMaxHeap<E> implements PriorityQueue<E> {
private E[] tree;
private int size;
private Comparator<? super E> cmp = null;
/**
* BinaryMaxHeap constructor with no parameters
*/
@SuppressWarnings("unchecked")
public BinaryMaxHeap() {
tree = (E[]) new Object[100];
size = 0;
}
/**
* BinaryMaxHeap constructor that allows for a specified comparator
*
* @param cmp - comparator to use for BinaryMaxHeap
*/
public BinaryMaxHeap(Comparator<? super E> cmp) {
this();
this.cmp = cmp;
}
/**
* BinaryMaxHeap constructor that is built off a parameter list
*
* @param list - list to build BinaryMaxHeap from
*/
public BinaryMaxHeap(List<? extends E> list) {
buildHeap(list);
}
/**
* BinaryMaxHeap constructor that allows for a specified comparator and is built
* off a parameter list
*
* @param cmp - comparator to use for BinaryMaxHeap
* @param list - list to build BinaryMaxHeap from
*/
public BinaryMaxHeap(List<? extends E> list, Comparator<? super E> cmp) {
this.cmp = cmp;
buildHeap(list);
}
/**
* Private helper method for BinaryMaxHeap constructors that turns a parameter
* list into a BinaryMaxHeap
*
* @param list - list to build BinaryMaxHeap from
*/
@SuppressWarnings("unchecked")
private void buildHeap(List<? extends E> list) {
// Creates a tree to move list elements into
tree = (E[]) new Object[list.size() + 1];
// Adds each element from list to tree
for (int i = 0; i < list.size(); i++)
tree[i + 1] = list.get(i);
size = list.size();
// PercolatesDown every element that is not leaf
for (int i = size / 2; i > 0; i--)
percolateDown(i);
}
/**
* Private helper method for percolating up an element in the tree
*
* @param index - index of element to be percolated up
*/
private void percolateUp(int index) {
// Checks that the element at index is greater than the element at the parent
// index, meaning a swap is valid
while (index > 1 && innerCompare(tree[index], tree[parent(index)]) > 0) {
swap(index, parent(index));
index = parent(index);
}
}
/**
* Private helper method for percolating down an element in the tree
*
* @param index - index of the element to be percolated down
*/
private void percolateDown(int index) {
// While index has a left child
while (leftChild(index) <= size) {
int biggestChildIndex = getBiggestChild(index);
// If the element at index is less than the larger of it's children
if (innerCompare(tree[index], tree[biggestChildIndex]) < 0)
// Index is swapped with the largest of it's children
swap(index, biggestChildIndex);
else
break;
// Index's biggest child is then used for the next iteration
index = biggestChildIndex;
}
}
/**
* Private helper method to double the size of the backing array
*/
@SuppressWarnings("unchecked")
private void doubleBacking() {
// Creates a new tree double the size of the previous
E[] newTree = (E[]) new Object[tree.length * 2];
// Adds each element from the previous tree to the new tree
for (int i = 1; i < tree.length; i++)
newTree[i] = tree[i];
// Sets tree to the new, larger, tree
tree = newTree;
}
/**
* Private helper method that swaps the element at one index with the element at
* another index
*
* @param index1 - Element to be swapped with the seconds element
* @param index2 - Element to be swapped with the first element
*/
private void swap(int index1, int index2) {
// Creates a temp element to store the value of element one
E tmp = tree[index1];
// Adds the respective values to elements being swapped
tree[index1] = tree[index2];
tree[index2] = tmp;
}
/**
* Private helper method that returns the parent index of an index in the tree
*
* @param index - index to find the parent of
*
* @return - parent index of "index"
*/
private int parent(int index) {
return index / 2;
}
/**
* Private helper method that returns the left child index of an index in the
* tree
*
* @param index - index to find the left child
*
* @return - the left child index of "index"
*/
private int leftChild(int index) {
return index * 2;
}
/**
* Private helper method that returns the right child index of an index in the
* tree
*
* @param index - index to find the right child
*
* @return - the right child index of "index"
*/
private int rightChild(int index) {
return (index * 2) + 1;
}
/**
* Private helper method to find the larger of two children from a given index
* in the tree
*
* @param index - to find the largest child of
*
* @return - the largest child of "index"
*/
private int getBiggestChild(int index) {
// First checks if the left is the last element in the tree to make sure
// rightChild() is not called. Then compares leftChild() and rightChild()
if (leftChild(index) == size || innerCompare(tree[leftChild(index)], tree[rightChild(index)]) > 0)
return leftChild(index);
return rightChild(index);
}
/**
* Private helper method that compares two elements
*
* @param element1 - First element to be compared
* @param element2 - Second element to be compared
*
* @return - Returns a value representing the comparison of the two elements
* either through natural ordering or a comparator if provided
*/
@SuppressWarnings("unchecked")
private int innerCompare(E element1, E element2) {
// If no comparator is provided, natural ordering is used
if (cmp == null)
return ((Comparable<? super E>) element1).compareTo(element2);
// Otherwise, the provided comparator is used
return cmp.compare(element1, element2);
}
/**
* Adds the given item to this BinaryMaxHeap. O(1) in the average case, O(log N)
* in the worst case
*
* @param item - Item to be added
*/
@Override
public void add(E item) {
if (size == tree.length - 1)
doubleBacking();
tree[++size] = item;
percolateUp(size);
}
/**
* Returns, but does not remove, the maximum item this BinaryMaxHeap. O(1)
*
* @return the maximum item
* @throws NoSuchElementException if this priority queue is empty
*/
@Override
public E peek() throws NoSuchElementException {
if (this.isEmpty())
throw new NoSuchElementException();
return tree[1];
}
/**
* Returns and removes the maximum item this BinaryMaxHeap. O(log N)
*
* @return the maximum item
* @throws NoSuchElementException if this priority queue is empty
*/
@Override
public E extractMax() throws NoSuchElementException {
// Throws an exception if the BinaryMaxHeap is empty
if (this.isEmpty())
throw new NoSuchElementException();
// Keeps track of the element being removed from the tree
E max = tree[1];
// Replaces the element being removed with the last element in the backing array
tree[1] = tree[size--];
// Percolates that last element to a correct location
percolateDown(1);
return max;
}
/**
* Returns the number of items in this BinaryMaxHeap. O(1)
*/
@Override
public int size() {
return size;
}
/**
* Returns true if this BinaryMaxHeap is empty, false otherwise. O(1)
*/
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* Empties this BinaryMaxHeap of items. O(1)
*/
@SuppressWarnings("unchecked")
@Override
public void clear() {
tree = (E[]) new Object[100];
size = 0;
}
/**
* Creates and returns an array of the items in this BinaryMaxHeap, in the same
* order they appear in the backing array. O(N)
*
* (NOTE: This method is needed for grading purposes. The root item must be
* stored at index 0 in the returned array, regardless of whether it is in
* stored there in the backing array.)
*/
@Override
public Object[] toArray() {
@SuppressWarnings("unchecked")
E[] treeCopy = (E[]) new Object[size];
for (int i = 1; i <= size; i++)
treeCopy[i - 1] = tree[i];
return treeCopy;
}
/**
* Private helper method for representing the BinaryMaxHeap while debugging
*
* @return - A basic multi-line representation of the BinaryMaxHeap
*/
@SuppressWarnings("unused")
private String stringRepresentation() {
StringBuilder result = new StringBuilder();
int end = 1;
for (int i = 1; i <= size; i++) {
result.append(tree[i]);
result.append(" ");
if (i == end) {
result.append("\n");
end = end * 2 + 1;
}
}
return result.toString();
}
}