堆是一颗完全被填满的二叉树,有可能的例外是在底层,底层的元素从左到右填满。完全二叉树
二叉堆又可分为最大堆,最小堆。最小堆就是节点元素值小于等于两儿子。
完全二叉树可以用一个数组表示,a[0] 位置空出(后面有用)
对于数组任意位置i上的元素, 其左儿子在位置2i上,右儿子在位置2i+1上, 父节点在i/2上。因此不需要链。问题在最大的堆的大小需要事先估计,但是一般不成问题,可以调整大小。
// BinaryHeap class
//
// CONSTRUCTION: with optional capacity (that defaults to 100)
// or an array containing initial items
//
// ******************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
// ******************ERRORS********************************
// Throws UnderflowException as appropriate
/**
* Implements a binary heap.
* Note that all "matching" is based on the compareTo method.
* @author Mark Allen Weiss
*/
public class BinaryHeap<AnyType extends Comparable<? super AnyType>>
{
/**
* Construct the binary heap.
*/
public BinaryHeap( )
{
this( DEFAULT_CAPACITY );
}
/**
* Construct the binary heap.
* @param capacity the capacity of the binary heap.
*/
public BinaryHeap( int capacity )
{
currentSize = 0;
array = (AnyType[]) new Comparable[ capacity + 1 ];
}
/**
* Construct the binary heap given an array of items.
*/
public BinaryHeap( AnyType [ ] items )
{
currentSize = items.length;
array = (AnyType[]) new Comparable[ ( currentSize + 2 ) * 11 / 10 ];
int i = 1;
for( AnyType item : items )
array[ i++ ] = item;
buildHeap( );
}
/**
* Insert into the priority queue, maintaining heap order.
* Duplicates are allowed.
* @param x the item to insert.
*/
public void insert( AnyType x )
{
if( currentSize == array.length - 1 )
enlargeArray( array.length * 2 + 1 );
// Percolate up
int hole = ++currentSize;
for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
array[ hole ] = array[ hole / 2 ];
array[ hole ] = x;
}
private void enlargeArray( int newSize )
{
AnyType [] old = array;
array = (AnyType []) new Comparable[ newSize ];
for( int i = 0; i < old.length; i++ )
array[ i ] = old[ i ];
}
/**
* Find the smallest item in the priority queue.
* @return the smallest item, or throw an UnderflowException if empty.
*/
public AnyType findMin( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return array[ 1 ];
}
/**
* Remove the smallest item from the priority queue.
* @return the smallest item, or throw an UnderflowException if empty.
*/
public AnyType deleteMin( )
{
if( isEmpty( ) )
throw new UnderflowException( );
AnyType minItem = findMin( );
array[ 1 ] = array[ currentSize-- ];
percolateDown( 1 );
return minItem;
}
/**
* Establish heap order property from an arbitrary
* arrangement of items. Runs in linear time.
*/
private void buildHeap( )
{
for( int i = currentSize / 2; i > 0; i-- )
percolateDown( i );
}
/**
* Test if the priority queue is logically empty.
* @return true if empty, false otherwise.
*/
public boolean isEmpty( )
{
return currentSize == 0;
}
/**
* Make the priority queue logically empty.
*/
public void makeEmpty( )
{
currentSize = 0;
}
private static final int DEFAULT_CAPACITY = 10;
private int currentSize; // Number of elements in heap
private AnyType [ ] array; // The heap array
/**
* Internal method to percolate down in the heap.
* @param hole the index at which the percolate begins.
*/
private void percolateDown( int hole )
{
int child;
AnyType 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;
}
// Test program
public static void main( String [ ] args )
{
int numItems = 10000;
BinaryHeap<Integer> h = new BinaryHeap<>( );
int i = 37;
for( i = 37; i != 0; i = ( i + 37 ) % numItems )
h.insert( i );
for( i = 1; i < numItems; i++ )
if( h.deleteMin( ) != i )
System.out.println( "Oops! " + i );
}
}