package changsheng.algorithms.heap;
// PriorityQueue interface
//
// ******************PUBLIC OPERATIONS*********************
// void insert( x ) --> Insert x
// Comparable deleteMin( )--> Return and remove smallest item
// Comparable findMin( ) --> Return smallest item
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// int size( ) --> Return size
// ******************ERRORS********************************
// Throws UnderflowException for findMin and deleteMin when empty
public interface PriorityQueue<E extends Comparable<? super E>>
{
/**
* Insert into the priority queue, maintaining heap order.
* Duplicates are allowed.
* @param x the item to insert.
*/
void insert( E x );
/**
* Find the smallest item in the priority queue.
* @return the smallest item.
* @throws UnderflowException if empty.
*/
E findMin( );
/**
* Remove the smallest item from the priority queue.
* @return the smallest item.
* @throws UnderflowException if empty.
*/
E deleteMin( );
/**
* Test if the priority queue is logically empty.
* @return true if empty, false otherwise.
*/
boolean isEmpty( );
/**
* Make the priority queue logically empty.
*/
void makeEmpty( );
/**
* Returns the size.
* @return current size.
*/
int size( );
}
package changsheng.algorithms.heap;
import java.util.Arrays;
import changsheng.algorithms.util.EmptyQueueException;
import changsheng.algorithms.util.Swap;
public class DefaultPriorityQueue<E extends Comparable<? super E>> implements
PriorityQueue<E> {
private E[] array;
private int DEFAULT_SIZE = 10;
private int currentSize = 0;
public DefaultPriorityQueue() {
makeEmpty();
}
/**
* Construct the binary heap from an array.
*
* @param items
* the inital items in the binary heap.
*/
@SuppressWarnings("unchecked")
public DefaultPriorityQueue(E[] items) {
currentSize = items.length;
array = (E[]) new Comparable[items.length + 1];
for (int i = 0; i < items.length; i++)
array[i + 1] = items[i];
BuildMaxHeap();
}
@Override
public void insert(E x) {
if ((currentSize + 1) == array.length) {
allocateArray(array.length * 2);
}
int hole = ++currentSize;
array[0] = x;
while (x.compareTo(array[hole / 2]) < 0) {
array[hole] = array[hole / 2];
hole /= 2;
}
array[hole] = x;
}
private void allocateArray(int size) {
array = Arrays.copyOf(array, size);
}
@Override
public E findMin() {
if (isEmpty()) {
throw new EmptyQueueException("Empty binary heap !");
}
return array[1];
}
@Override
public E deleteMin() {
if (isEmpty()) {
throw new EmptyQueueException("Empty binary heap !");
}
E min = findMin();
array[1] = array[currentSize--];
MaxHeapify(1);
return min;
}
/**
* 建堆时必须自底向上建立
*/
private void BuildMaxHeap() {
int len = array.length;
for (int i = len / 2; i >= 1; i--) {
MaxHeapify(i);
}
}
/*
* 递归调用
*/
private void MaxHeapify(int i) {
/**
* 在i(节点)、2*i(左孩子)和2*i+1(右孩子)中选出一个最小索引smallest。 如果smallest == i
* 说明已满足小顶堆的特性,退出递归调用。 如果smallest != i
* 说明三者不满足小顶堆的特性,将smallest与i位置上的值进行交换。 然后再以smallest为参数进行MaxHeapify调用。
*/
int left = 2 * i;
int right = 2 * i + 1;
int smallest = i;
if (left <= currentSize && array[left].compareTo(array[smallest]) < 0) {
smallest = left;
}
if (right <= currentSize && array[right].compareTo(array[smallest]) < 0) {
smallest = right;
}
if (smallest != i) {
Swap.swap(array, i, smallest);
MaxHeapify(smallest);
}
}
/**
* 非递归调用
*/
@SuppressWarnings("unused")
private void MaxHeapifyNormal(int hole) {
int child;
E tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child) {
child = hole * 2;
if (child != currentSize
&& array[child + 1].compareTo(array[child]) < 0)
child++;
if (array[child].compareTo(tmp) < 0)
array[hole] = array[child];
else
break;
}
array[hole] = tmp;
}
@Override
public boolean isEmpty() {
return currentSize == 0;
}
@SuppressWarnings("unchecked")
@Override
public void makeEmpty() {
array = (E[]) new Comparable[DEFAULT_SIZE];
currentSize = 0;
}
@Override
public int size() {
return currentSize;
}
public static void main(String[] args) {
int numItems = 10000;
DefaultPriorityQueue<Integer> h1 = new DefaultPriorityQueue<Integer>();
Integer[] items = new Integer[numItems - 1];
int i = 37;
int j;
for (i = 37, j = 0; i != 0; i = (i + 37) % numItems, j++) {
h1.insert(i);
items[j] = i;
}
for (i = 1; i < numItems; i++)
if (h1.deleteMin() != i)
System.out.println("Oops! " + i);
}
}