#include "SplayTree.h" #include "Except.h" // Construct the tree. template SplayTree:: SplayTree( ) { nullNode = new BinaryNode; nullNode->left = nullNode->right = nullNode; root = nullNode; } // Copy constructor. template SplayTree:: SplayTree( const SplayTree & rhs ) { nullNode = new BinaryNode; nullNode->left = nullNode->right = nullNode; root = nullNode; *this = rhs; } // Destructor. template SplayTree:: ~SplayTree( ) { makeEmpty( ); delete nullNode; } // Insert x into the tree. // Throws DuplicateItemException if x is already there. template void SplayTree:: insert( const Comparable & x ) { static BinaryNode *newNode = NULL; if( newNode == NULL ) newNode = new BinaryNode; newNode->element = x; if( root == nullNode ) { newNode->left = newNode->right = nullNode; root = newNode; } else { splay( x, root ); if( x < root->element ) { newNode->left = root->left; newNode->right = root; root->left = nullNode; root = newNode; } else if( root->element < x ) { newNode->right = root->right; newNode->left = root; root->right = nullNode; root = newNode; } else throw DuplicateItemException( ); } newNode = NULL; // So next insert will call new } // Remove x from the tree. // Throws ItemNotFoundException if x is not in the tree. template void SplayTree:: remove( const Comparable & x ) { BinaryNode *newTree; // If x is found, it will be at the root splay( x, root ); if( root->element != x ) throw ItemNotFoundException( ); if( root->left == nullNode ) newTree = root->right; else { // Find the maximum in the left subtree // Splay it to the root; and then attach right child newTree = root->left; splay( x, newTree ); newTree->right = root->right; } delete root; root = newTree; } // Internal method to wrap the element field in node t inside a Cref object. template Cref SplayTree:: elementAt( BinaryNode *t ) const { return t == NULL ? Cref( ) : Cref( t->element ); } // Find the smallest item in the tree. // Not the most efficient implementation (uses two passes), but has correct // amortized behavior. // A good alternative is to first call find with parameter // smaller than any item in the tree, then call findMin. // Return the smallest item in the tree wrapped in a Cref object. template Cref SplayTree:: findMin( ) { if( isEmpty( ) ) return elementAt( NULL ); BinaryNode *ptr = root; while( ptr->left != nullNode ) ptr = ptr->left; splay( ptr->element, root ); return elementAt( root ); } // Find the largest item in the tree. // Not the most efficient implementation (uses two passes), but has correct // amortized behavior. // A good alternative is to first call Find with parameter // larger than any item in the tree, then call findMax. // Return the largest item in the tree wrapped in a Cref object. template Cref SplayTree:: findMax( ) { if( isEmpty( ) ) return elementAt( NULL ); BinaryNode *ptr = root; while( ptr->right != nullNode ) ptr = ptr->right; splay( ptr->element, root ); return elementAt( root ); } // Find item x in the tree. // Return the matching item wrapped in a Cref object. template Cref SplayTree:: find( const Comparable & x ) { splay( x, root ); if( isEmpty( ) || root->element != x ) return elementAt( NULL ); return elementAt( root ); } // Make the tree logically empty. template void SplayTree:: makeEmpty( ) { findMax( ); // Splay max item to root while( !isEmpty( ) ) remove( root->element ); } // Test if the tree is logically empty. // Return true if empty, false otherwise. template bool SplayTree:: isEmpty( ) const { return root == nullNode; } // Deep copy. template const SplayTree & SplayTree:: operator=( const SplayTree & rhs ) { if( this != &rhs ) { makeEmpty( ); root = clone( rhs.root ); } return *this; } // Internal method to perform a top-down splay. // The last accessed node becomes the new root. // x is the target item to splay around. // t is the root of the subtree to splay. template void SplayTree:: splay( const Comparable & x, BinaryNode * & t ) const { BinaryNode *leftTreeMax, *rightTreeMin; static BinaryNode header; header.left = header.right = nullNode; leftTreeMax = rightTreeMin = &header; nullNode->element = x; // Guarantee a match for( ; ; ) if( x < t->element ) { if( x < t->left->element ) rotateWithLeftChild( t ); if( t->left == nullNode ) break; // Link Right rightTreeMin->left = t; rightTreeMin = t; t = t->left; } else if( t->element < x ) { if( t->right->element < x ) rotateWithRightChild( t ); if( t->right == nullNode ) break; // Link Left leftTreeMax->right = t; leftTreeMax = t; t = t->right; } else break; leftTreeMax->right = t->left; rightTreeMin->left = t->right; t->left = header.right; t->right = header.left; } // Rotate binary tree node with left child. template void SplayTree:: rotateWithLeftChild( BinaryNode * & k2 ) const { BinaryNode *k1 = k2->left; k2->left = k1->right; k1->right = k2; k2 = k1; } // Rotate binary tree node with right child. template void SplayTree:: rotateWithRightChild( BinaryNode * & k1 ) const { BinaryNode *k2 = k1->right; k1->right = k2->left; k2->left = k1; k1 = k2; } // Internal method to reclaim internal nodes in subtree t. // WARNING: This is prone to running out of stack space. template void SplayTree:: reclaimMemory( BinaryNode * t ) const { if( t != t->left ) { reclaimMemory( t->left ); reclaimMemory( t->right ); delete t; } } // Internal method to clone subtree. // WARNING: This is prone to running out of stack space. template BinaryNode * SplayTree:: clone( BinaryNode * t ) const { if( t == t->left ) // Cannot test against nullNode!!! return nullNode; else return new BinaryNode( t->element, clone( t->left ), clone( t->right ) ); }