I'm just looking for some feedback on my implementation of a maxheap mostly relating to style. I'm trying to create good habits as I learn to program.
Note: for the sort method I was given the precondition that the passed in array never has empty/null elements and that it must be sorted in place.
public class Heap12<E extends Comparable<? super E>> implements PQueue<E>{
private E[] heap; // Backend data storage array
private int size; // # elements in the heap
Private constructor that is used by the sort()
method to heapify an array of objects type E
. Size
is initialized to 0 so that the objects in the array can be sorted in place by calling the add(E e)
method.
@param E[] e
- the array to be heapified
@SuppressWarnings("unchecked")
private Heap12(E[] e){
this.heap = e; // Set heap array to passed in array
this.size = 0; // Size HAS to be 0 initially
}
Public default no-arg constructor that initializes size to 0 and the backing array to a default capacity.
@SuppressWarnings("unchecked")
public Heap12(){
this.size = 0; // Default values
this.heap = (E[]) new Comparable[5];
}
Public copy constructor that takes in another Heap12<E>
object. It creates
a new Heap12<E>
object that is a deep copy of the passed in object. The underlying objects of the backing array are shared, but each Heap12
has its own instance variables.
@param Heap12<E> o
- the Heap12<E>
object to be copied
@SuppressWarnings("unchecked")
public Heap12(Heap12<E> o){
this.heap = (E[]) new Comparable[o.heap.length];
this.size = o.size; // Copy size
for(int i = 0; i < o.size(); i++){ // Copy each element
this.heap[i] = o.heap[i]; // reference
}
}
Adds an element to this Heap12
object. Does not accept null elements, will throw a NullPointerException
. If the Heap12
is at maximum capacity, the capacity will be doubled before adding the element.
@param E e
- the element to be added to the Heap12
public void add(E e){
if(e == null) // Check for null element add
throw new NullPointerException();
if(this.size() == heap.length)
expandHeap(); // Double heap capacity if full
heap[this.size()] = e; // Add the element at the rightmost leaflet
bubbleUp(this.size()); // Move it to its proper place
size++;
}
Returns the largest element contained in the Heap12
object (the root). Does not modify the heap.
@return E
- the largest object (the object at the root)
public E peek(){
return heap[0];
}
Removes the largest element in this heap (the root). If the heap is empty, null is returned.
@return E
- the largest element (the root)
public E remove(){
E toReturn;
if(this.isEmpty()) // Empty heap case
return null;
toReturn = heap[0]; // Return greatest element(root)
heap[0] = heap[this.size() - 1]; // Put bottom rightmost at root
heap[this.size() - 1] = null; // Get rid of the copy
size--;
trickleDown(0); // Move the new root to its proper
// place
return toReturn;
}
Determines if this Heap12
is equal to the passed in object. Returns false if the passed in object is not a Heap12
, the two Heap12
's have different sizes (# of elements), or if the two Heap12
objects do not have the same underlying data, in the same order.
@param Object
o - the object to compare this Heap12
with @return
boolean whether the two objects are equal
public boolean equals(Object o){
if( !(o instanceof Heap12) ) // Type check
return false;
Heap12 oQ = (Heap12) o;
if(this.size() != oQ.size()) // Diff # elements means diff heaps
return false;
for(int i = 0; i < this.size(); i++){ // Loop through all the elements
if( !(this.heap[i].equals(oQ.heap[i])) ) // if one is different
return false; // heaps are not equal
}
return true; // If we get here, heaps are equal
}
Returns a hash code for this Heap12
object. The code is the same for objects that contain the same elements in the same order.
@return int
- the hash code of this Heap12<E>
public int hashCode(){
int toReturn = 1;
/* Add each elements hashCode to the total and multiples by 31 each time */
for(int i = 0; i < this.size(); i++){
toReturn = 31 * toReturn + heap[i].hashCode();
}
return toReturn;
}
Checks to see if this Heap12<E>
is empty (has no elements)
@return boolean
- true if the Heap12
is empty, false if not
public boolean isEmpty(){
return size == 0;
}
Returns the number of elements in this Heap12<E>
object as an int. @return
- the number of elements in this Heap12
object.
public int size(){
return this.size;
}
Private helper method for remove()
. This method reorders the underlying heap array after an element is removed so that the heap retains the max heap property and completeness.
@param int parent
- the parent node index
private void trickleDown(int parent){
int left = (2 * parent) + 1; // Compute Left/Right child indices
int right = (2 * parent) + 2;
if(left > size - 1 ) // Base case: end of the heap
return;
/* If right child is null or left child >= right child, compare left child
to parent */
if(heap[right] == null || heap[left].compareTo(heap[right]) >= 0){
if(heap[left].compareTo(heap[parent]) > 0){
swap(parent, left); // If the left child is > parent swap
trickleDown(left); // Left index is now the parent index
}
} // If the right child > parent
else if(heap[right].compareTo(heap[parent]) > 0){
swap(parent, right); // Swap the parent and right child
trickleDown(right); // Right index is now the parent index
}
}
Private helper method for add(E e)
. This method reorders the underlying heap array after an element is added so that the heap retains the max heap property and completeness.
@param int child
- the child node index
private void bubbleUp(int child){
int parent = (child - 1) / 2; // Compute the parent index
if(child == 0) // If we're at the root, stop bubbling
return; // Added simply for clarity (not needed)
if( heap[child].compareTo(heap[parent]) > 0 ){ // If child > parent
swap(parent, child); // Swap them
bubbleUp(parent); // parent is now the old child
}
}
Private helper method that swaps a parent node element and a child node element using a temp variable.
@param int parent
- the index of the parent object
@param int child
- the index of the child object
private void swap(int parent, int child){
E temp = heap[parent]; // Store the parent
heap[parent] = heap[child]; // Replace parent element with child
heap[child] = temp; // Replace child with the parent
}
Private helper method that doubles the capacity of the underlying array of this Heap12
object. Used when trying to add an element to a heap where size == capacity
.
@SuppressWarnings("unchecked")
private void expandHeap(){ // Create new array with double capacity
E[] temp = (E[]) new Comparable[heap.length * 2];
for(int i = 0; i < heap.length; i++){
temp[i] = this.heap[i]; // Copy all the references
}
this.heap = temp; // Update instance backing array
}
Static sort method that sorts the passed in array in place using a heap. The sorted array is in ascending order. The passed in array must be full and not contain any null elements.
@param T[] a
- the array of objects to be sorted in ascending order
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(T[] a){
Heap12<T> sorted = new Heap12<T>(a); // Use unsorted array as heap
// backing array in new Heap12
/* Add each array element to the heap, it will sort itself in place */
for(int i = 0; i < sorted.heap.length; i++)
sorted.add(sorted.heap[sorted.size()]); // Size is initially 0
/* Remove each heap element, put it at the end of the underlying array */
while(sorted.size() > 0)
sorted.heap[sorted.size() - 1] = sorted.remove();
}
}