package ags.utils.dataStructures; import java.util.Arrays; /** * An implementation of an implicit binary heap. Min-heap and max-heap both supported */ public abstract class BinaryHeap<T> { protected static final int defaultCapacity = 64; private final int direction; private Object[] data; private double[] keys; private int capacity; private int size; protected BinaryHeap(int capacity, int direction) { this.direction = direction; this.data = new Object[capacity]; this.keys = new double[capacity]; this.capacity = capacity; this.size = 0; } public void offer(double key, T value) { // If move room is needed, double array size if (size >= capacity) { capacity *= 2; data = Arrays.copyOf(data, capacity); keys = Arrays.copyOf(keys, capacity); } // Insert new value at the end data[size] = value; keys[size] = key; siftUp(size); size++; } protected void removeTip() { if (size == 0) { throw new IllegalStateException(); } size--; data[0] = data[size]; keys[0] = keys[size]; data[size] = null; siftDown(0); } protected void replaceTip(double key, T value) { if (size == 0) { throw new IllegalStateException(); } data[0] = value; keys[0] = key; siftDown(0); } @SuppressWarnings("unchecked") protected T getTip() { if (size == 0) { throw new IllegalStateException(); } return (T) data[0]; } protected double getTipKey() { if (size == 0) { throw new IllegalStateException(); } return keys[0]; } private void siftUp(int c) { for (int p = (c - 1) / 2; c != 0 && direction*keys[c] > direction*keys[p]; c = p, p = (c - 1) / 2) { Object pData = data[p]; double pDist = keys[p]; data[p] = data[c]; keys[p] = keys[c]; data[c] = pData; keys[c] = pDist; } } private void siftDown(int p) { for (int c = p * 2 + 1; c < size; p = c, c = p * 2 + 1) { if (c + 1 < size && direction*keys[c] < direction*keys[c + 1]) { c++; } if (direction*keys[p] < direction*keys[c]) { // Swap the points Object pData = data[p]; double pDist = keys[p]; data[p] = data[c]; keys[p] = keys[c]; data[c] = pData; keys[c] = pDist; } else { break; } } } public int size() { return size; } public int capacity() { return capacity; } public static final class Max<T> extends BinaryHeap<T> implements MaxHeap<T> { public Max() { super(defaultCapacity, 1); } public Max(int capacity) { super(capacity, 1); } public void removeMax() { removeTip(); } public void replaceMax(double key, T value) { replaceTip(key, value); } public T getMax() { return getTip(); } public double getMaxKey() { return getTipKey(); } } public static final class Min<T> extends BinaryHeap<T> implements MinHeap<T> { public Min() { super(defaultCapacity, -1); } public Min(int capacity) { super(capacity, -1); } public void removeMin() { removeTip(); } public void replaceMin(double key, T value) { replaceTip(key, value); } public T getMin() { return getTip(); } public double getMinKey() { return getTipKey(); } } }