programming-examples/c++/Others/LeftistHeap.cpp - Implementation for leftist heap.cpp
2019-11-15 12:59:38 +01:00

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 );
}