171 lines
4.2 KiB
Java
171 lines
4.2 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*******************************************************************************/
|
|
package com.ibm.wala.util.collections;
|
|
|
|
import java.util.NoSuchElementException;
|
|
|
|
/**
|
|
* Simple Heap data structure.
|
|
*/
|
|
public abstract class Heap<T> {
|
|
|
|
/**
|
|
* @return true iff elt1 is considered < elt2
|
|
*/
|
|
abstract protected boolean compareElements(T elt1, T elt2);
|
|
|
|
private int numberOfElements;
|
|
|
|
private T[] backingStore;
|
|
|
|
/**
|
|
* @return number of elements in this heap
|
|
*/
|
|
public int size() {
|
|
return numberOfElements;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public Heap(int initialCapacity) {
|
|
numberOfElements = 0;
|
|
backingStore = (T[])new Object[initialCapacity];
|
|
}
|
|
|
|
/**
|
|
* @return true iff this heap is non-empty
|
|
*/
|
|
final public boolean isEmpty() {
|
|
return numberOfElements == 0;
|
|
}
|
|
|
|
|
|
public void insert(T elt) {
|
|
ensureCapacity(numberOfElements + 1);
|
|
bubbleUp(elt, numberOfElements);
|
|
numberOfElements++;
|
|
}
|
|
|
|
/**
|
|
* @return the first object in the priority queue
|
|
*/
|
|
public T take() throws NoSuchElementException {
|
|
if (numberOfElements == 0) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
T result = backingStore[0];
|
|
removeElement(0);
|
|
return result;
|
|
}
|
|
|
|
private static int heapParent(int index) {
|
|
return (index - 1) / 2;
|
|
}
|
|
|
|
private static int heapLeftChild(int index) {
|
|
return index * 2 + 1;
|
|
}
|
|
|
|
private static int heapRightChild(int index) {
|
|
return index * 2 + 2;
|
|
}
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
final private void ensureCapacity(int min) {
|
|
if (backingStore.length < min) {
|
|
T newStore[] = (T[])new Object[2 * min];
|
|
System.arraycopy(backingStore, 0, newStore, 0, backingStore.length);
|
|
backingStore = newStore;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SJF: I know this is horribly uglified ... I've attempted to make things as
|
|
* easy as possible on the JIT, since this is performance critical.
|
|
*
|
|
* @param index
|
|
*/
|
|
final private void removeElement(int index) {
|
|
int ne = numberOfElements;
|
|
T[] bs = backingStore;
|
|
while (true) {
|
|
int leftIndex = heapLeftChild(index);
|
|
if (leftIndex < ne) {
|
|
int rightIndex = heapRightChild(index);
|
|
if (rightIndex < ne) {
|
|
T leftObject = bs[leftIndex];
|
|
T rightObject = bs[rightIndex];
|
|
if (compareElements(leftObject, rightObject)) {
|
|
bs[index] = leftObject;
|
|
index = leftIndex;
|
|
} else {
|
|
bs[index] = rightObject;
|
|
index = rightIndex;
|
|
}
|
|
} else {
|
|
bs[index] = bs[leftIndex];
|
|
index = leftIndex;
|
|
}
|
|
// manual tail recursion elimination here
|
|
} else {
|
|
numberOfElements--;
|
|
ne = numberOfElements;
|
|
if (index != ne) {
|
|
bubbleUp(bs[ne], index);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SJF: I know this is uglified ... I've attempted to make things as easy as
|
|
* possible on the JIT, since this is performance critical.
|
|
*
|
|
* @param elt
|
|
* @param index
|
|
*/
|
|
final private void bubbleUp(T elt, int index) {
|
|
T[] bs = backingStore;
|
|
while (true) {
|
|
if (index == 0) {
|
|
bs[index] = elt;
|
|
return;
|
|
}
|
|
int hpIndex = heapParent(index);
|
|
T parent = bs[hpIndex];
|
|
if (compareElements(parent, elt)) {
|
|
bs[index] = elt;
|
|
return;
|
|
} else {
|
|
bs[index] = parent;
|
|
// manual tail recursion elimination
|
|
index = hpIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
StringBuffer s = new StringBuffer();
|
|
s.append("[");
|
|
for (int i = 0; i < size(); i++) {
|
|
if (backingStore[i] != null) {
|
|
if (i > 0)
|
|
s.append(",");
|
|
s.append(backingStore[i].toString());
|
|
}
|
|
}
|
|
s.append("]");
|
|
return s.toString();
|
|
}
|
|
}
|