|
@ -0,0 +1,160 @@ |
|
|
|
|
|
package net.jrtechs.www.DataStructures.Trees.Heap; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import net.jrtechs.www.DataStructures.Lists.ArrayList.ArrayBackedList; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Basic implementation of a {@link IHeap}. By default, this is |
|
|
|
|
|
* a min heap, however, using the second constructor with |
|
|
|
|
|
* (BinaryHeap.MAX_HEAP) will create a max heap. To keep the |
|
|
|
|
|
* performance of using an array, while having a dynamically scalable |
|
|
|
|
|
* heap, {@link ArrayBackedList} was used since it. |
|
|
|
|
|
* |
|
|
|
|
|
* Operation complexities: |
|
|
|
|
|
* insertion: O(logN) |
|
|
|
|
|
* delete extrema: O(logN) |
|
|
|
|
|
* get extrema: O(1) |
|
|
|
|
|
* |
|
|
|
|
|
* Basic Heap Operations: |
|
|
|
|
|
* Parent index = (i-1)/2 or (i-2)/2 |
|
|
|
|
|
* Left Node = 2n + 1 |
|
|
|
|
|
* Right Node = 2n + 1 |
|
|
|
|
|
* |
|
|
|
|
|
* @author Jeffery Russell 8-26-18 |
|
|
|
|
|
*/ |
|
|
|
|
|
public class BinaryHeap<E extends Comparable> |
|
|
|
|
|
implements IHeap<E> |
|
|
|
|
|
{ |
|
|
|
|
|
/** Used to define comparisons for a Max heap */ |
|
|
|
|
|
public static final int MAX_HEAP = -1; |
|
|
|
|
|
|
|
|
|
|
|
/** Used to define comparisons for a Min heap */ |
|
|
|
|
|
public static final int MIN_HEAP = 1; |
|
|
|
|
|
|
|
|
|
|
|
/** Where the heap is storing data */ |
|
|
|
|
|
private ArrayBackedList<E> data; |
|
|
|
|
|
|
|
|
|
|
|
/** Ordering which heap is using defined by |
|
|
|
|
|
* MAX_HEAP, and MIN_HEAP */ |
|
|
|
|
|
private int ordering; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Creates a new min Binary Heap |
|
|
|
|
|
*/ |
|
|
|
|
|
public BinaryHeap() |
|
|
|
|
|
{ |
|
|
|
|
|
this.data = new ArrayBackedList<>(); |
|
|
|
|
|
this.ordering = MIN_HEAP; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Creates a new binary heap with a specific ordering defined by |
|
|
|
|
|
* the MAX_HEAP, and MIN_HEAP constants |
|
|
|
|
|
* |
|
|
|
|
|
* @param ordering type of ordering to use |
|
|
|
|
|
*/ |
|
|
|
|
|
public BinaryHeap(int ordering) |
|
|
|
|
|
{ |
|
|
|
|
|
this.ordering = ordering; |
|
|
|
|
|
this.data = new ArrayBackedList<>(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Inserts a new element at the end of the array, and then shifts it |
|
|
|
|
|
* up to perserve the order of the heap. |
|
|
|
|
|
* |
|
|
|
|
|
* @param o element to insert |
|
|
|
|
|
*/ |
|
|
|
|
|
@Override |
|
|
|
|
|
public void insert(E o) |
|
|
|
|
|
{ |
|
|
|
|
|
this.data.add(o); |
|
|
|
|
|
this.shiftUp(this.data.size() -1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Preserves structure of heap after a element has been |
|
|
|
|
|
* added to the end of the heap. |
|
|
|
|
|
* |
|
|
|
|
|
* @param nodeIndex index of node to recursively bring up |
|
|
|
|
|
*/ |
|
|
|
|
|
private void shiftUp(int nodeIndex) |
|
|
|
|
|
{ |
|
|
|
|
|
if(nodeIndex != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
int parentIndex = (nodeIndex -1)/2; |
|
|
|
|
|
|
|
|
|
|
|
if(data.get(parentIndex).compareTo(data.get(nodeIndex)) == ordering) |
|
|
|
|
|
{ |
|
|
|
|
|
data.swap(nodeIndex, parentIndex); |
|
|
|
|
|
|
|
|
|
|
|
shiftUp(parentIndex); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Preserves the order of heap after the top element has been |
|
|
|
|
|
* removed. |
|
|
|
|
|
* |
|
|
|
|
|
* @param i index of element to recursively heapify |
|
|
|
|
|
*/ |
|
|
|
|
|
private void heapify(int i) |
|
|
|
|
|
{ |
|
|
|
|
|
int left = 2 * i + 1; |
|
|
|
|
|
int right = 2 * i + 2; |
|
|
|
|
|
|
|
|
|
|
|
int extrema = (left < data.size() && |
|
|
|
|
|
data.get(left).compareTo(data.get(i)) != ordering) |
|
|
|
|
|
? left : i; |
|
|
|
|
|
extrema = (right < data.size() && |
|
|
|
|
|
data.get(right).compareTo(data.get(extrema)) != ordering) |
|
|
|
|
|
? right: extrema; |
|
|
|
|
|
|
|
|
|
|
|
if(extrema != i) |
|
|
|
|
|
{ |
|
|
|
|
|
this.data.swap(i, extrema); |
|
|
|
|
|
heapify(extrema); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Removes the top element of the heap. |
|
|
|
|
|
* |
|
|
|
|
|
* @return top element |
|
|
|
|
|
*/ |
|
|
|
|
|
@Override |
|
|
|
|
|
public E remove() |
|
|
|
|
|
{ |
|
|
|
|
|
if(this.data.size() == 0) |
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
|
|
E element = this.data.get(0); |
|
|
|
|
|
|
|
|
|
|
|
this.data.set(0, this.data.remove(this.data.size() -1)); |
|
|
|
|
|
|
|
|
|
|
|
this.heapify(0); |
|
|
|
|
|
|
|
|
|
|
|
return element; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Returns the min/max value of the heep |
|
|
|
|
|
* |
|
|
|
|
|
* @return extrema value |
|
|
|
|
|
*/ |
|
|
|
|
|
@Override |
|
|
|
|
|
public E peek() |
|
|
|
|
|
{ |
|
|
|
|
|
if(data.size() == 0) |
|
|
|
|
|
return null; |
|
|
|
|
|
return data.get(0); |
|
|
|
|
|
} |
|
|
|
|
|
} |