224 lines
6.6 KiB
C++
224 lines
6.6 KiB
C++
|
LeftistHeap.cpp - Implementation for leftist heap
|
||
|
|
||
|
#include "LeftistHeap.h"
|
||
|
#include "dsexceptions.h"
|
||
|
|
||
|
/**
|
||
|
* Construct the leftist heap.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistHeap<Comparable>::LeftistHeap( )
|
||
|
{
|
||
|
root = NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copy constructor.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistHeap<Comparable>::LeftistHeap( const LeftistHeap<Comparable> & rhs )
|
||
|
{
|
||
|
root = NULL;
|
||
|
*this = rhs;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Destruct the leftist heap.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistHeap<Comparable>::~LeftistHeap( )
|
||
|
{
|
||
|
makeEmpty( );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Merge rhs into the priority queue.
|
||
|
* rhs becomes empty. rhs must be different from this.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::merge( LeftistHeap & rhs )
|
||
|
{
|
||
|
if( this == &rhs ) // Avoid aliasing problems
|
||
|
return;
|
||
|
|
||
|
root = merge( root, rhs.root );
|
||
|
rhs.root = NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Internal method to merge two roots.
|
||
|
* Deals with deviant cases and calls recursive merge1.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistNode<Comparable> *
|
||
|
LeftistHeap<Comparable>::merge( LeftistNode<Comparable> * h1,
|
||
|
LeftistNode<Comparable> * h2 ) const
|
||
|
{
|
||
|
if( h1 == NULL )
|
||
|
return h2;
|
||
|
if( h2 == NULL )
|
||
|
return h1;
|
||
|
if( h1->element < h2->element )
|
||
|
return merge1( h1, h2 );
|
||
|
else
|
||
|
return merge1( h2, h1 );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Internal method to merge two roots.
|
||
|
* Assumes trees are not empty, and h1's root contains smallest item.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistNode<Comparable> *
|
||
|
LeftistHeap<Comparable>::merge1( LeftistNode<Comparable> * h1,
|
||
|
LeftistNode<Comparable> * h2 ) const
|
||
|
{
|
||
|
if( h1->left == NULL ) // Single node
|
||
|
h1->left = h2; // Other fields in h1 already accurate
|
||
|
else
|
||
|
{
|
||
|
h1->right = merge( h1->right, h2 );
|
||
|
if( h1->left->npl < h1->right->npl )
|
||
|
swapChildren( h1 );
|
||
|
h1->npl = h1->right->npl + 1;
|
||
|
}
|
||
|
return h1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Swaps t's two children.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::swapChildren( LeftistNode<Comparable> * t ) const
|
||
|
{
|
||
|
LeftistNode<Comparable> *tmp = t->left;
|
||
|
t->left = t->right;
|
||
|
t->right = tmp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Insert item x into the priority queue, maintaining heap order.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::insert( const Comparable & x )
|
||
|
{
|
||
|
root = merge( new LeftistNode<Comparable>( x ), root );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Find the smallest item in the priority queue.
|
||
|
* Return the smallest item, or throw Underflow if empty.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
const Comparable & LeftistHeap<Comparable>::findMin( ) const
|
||
|
{
|
||
|
if( isEmpty( ) )
|
||
|
throw Underflow( );
|
||
|
return root->element;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove the smallest item from the priority queue.
|
||
|
* Throws Underflow if empty.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::deleteMin( )
|
||
|
{
|
||
|
if( isEmpty( ) )
|
||
|
throw Underflow( );
|
||
|
|
||
|
LeftistNode<Comparable> *oldRoot = root;
|
||
|
root = merge( root->left, root->right );
|
||
|
delete oldRoot;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove the smallest item from the priority queue.
|
||
|
* Pass back the smallest item, or throw Underflow if empty.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::deleteMin( Comparable & minItem )
|
||
|
{
|
||
|
minItem = findMin( );
|
||
|
deleteMin( );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test if the priority queue is logically empty.
|
||
|
* Returns true if empty, false otherwise.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
bool LeftistHeap<Comparable>::isEmpty( ) const
|
||
|
{
|
||
|
return root == NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test if the priority queue is logically full.
|
||
|
* Returns false in this implementation.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
bool LeftistHeap<Comparable>::isFull( ) const
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Make the priority queue logically empty.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::makeEmpty( )
|
||
|
{
|
||
|
reclaimMemory( root );
|
||
|
root = NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Deep copy.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
const LeftistHeap<Comparable> &
|
||
|
LeftistHeap<Comparable>::
|
||
|
operator=( const LeftistHeap<Comparable> & rhs )
|
||
|
{
|
||
|
if( this != &rhs )
|
||
|
{
|
||
|
makeEmpty( );
|
||
|
root = clone( rhs.root );
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Internal method to make the tree empty.
|
||
|
* WARNING: This is prone to running out of stack space;
|
||
|
* exercises suggest a solution.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
void LeftistHeap<Comparable>::reclaimMemory( LeftistNode<Comparable> * t ) const
|
||
|
{
|
||
|
if( t != NULL )
|
||
|
{
|
||
|
reclaimMemory( t->left );
|
||
|
reclaimMemory( t->right );
|
||
|
delete t;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Internal method to clone subtree.
|
||
|
* WARNING: This is prone to running out of stack space.
|
||
|
* exercises suggest a solution.
|
||
|
*/
|
||
|
template <class Comparable>
|
||
|
LeftistNode<Comparable> *
|
||
|
LeftistHeap<Comparable>::clone( LeftistNode<Comparable> * t ) const
|
||
|
{
|
||
|
if( t == NULL )
|
||
|
return NULL;
|
||
|
else
|
||
|
return new LeftistNode<Comparable>( t->element, clone( t->left ),
|
||
|
clone( t->right ), t->npl );
|
||
|
}
|