#include "LeftistHeap.h" #include "dsexceptions.h" /** * Construct the leftist heap. */ template LeftistHeap::LeftistHeap( ) { root = NULL; } /** * Copy constructor. */ template LeftistHeap::LeftistHeap( const LeftistHeap & rhs ) { root = NULL; *this = rhs; } /** * Destruct the leftist heap. */ template LeftistHeap::~LeftistHeap( ) { makeEmpty( ); } /** * Merge rhs into the priority queue. * rhs becomes empty. rhs must be different from this. */ template void LeftistHeap::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 LeftistNode * LeftistHeap::merge( LeftistNode * h1, LeftistNode * 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 LeftistNode * LeftistHeap::merge1( LeftistNode * h1, LeftistNode * 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 void LeftistHeap::swapChildren( LeftistNode * t ) const { LeftistNode *tmp = t->left; t->left = t->right; t->right = tmp; } /** * Insert item x into the priority queue, maintaining heap order. */ template void LeftistHeap::insert( const Comparable & x ) { root = merge( new LeftistNode( x ), root ); } /** * Find the smallest item in the priority queue. * Return the smallest item, or throw Underflow if empty. */ template const Comparable & LeftistHeap::findMin( ) const { if( isEmpty( ) ) throw Underflow( ); return root->element; } /** * Remove the smallest item from the priority queue. * Throws Underflow if empty. */ template void LeftistHeap::deleteMin( ) { if( isEmpty( ) ) throw Underflow( ); LeftistNode *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 void LeftistHeap::deleteMin( Comparable & minItem ) { minItem = findMin( ); deleteMin( ); } /** * Test if the priority queue is logically empty. * Returns true if empty, false otherwise. */ template bool LeftistHeap::isEmpty( ) const { return root == NULL; } /** * Test if the priority queue is logically full. * Returns false in this implementation. */ template bool LeftistHeap::isFull( ) const { return false; } /** * Make the priority queue logically empty. */ template void LeftistHeap::makeEmpty( ) { reclaimMemory( root ); root = NULL; } /** * Deep copy. */ template const LeftistHeap & LeftistHeap:: operator=( const LeftistHeap & 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 void LeftistHeap::reclaimMemory( LeftistNode * 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 LeftistNode * LeftistHeap::clone( LeftistNode * t ) const { if( t == NULL ) return NULL; else return new LeftistNode( t->element, clone( t->left ), clone( t->right ), t->npl ); }