#include #include "SplayTree.h" /** * Construct the tree. */ template SplayTree::SplayTree( const Comparable & notFound ) : ITEM_NOT_FOUND( notFound ) { nullNode = new BinaryNode; nullNode->left = nullNode->right = nullNode; nullNode->element = notFound; root = nullNode; } /** * Copy constructor. */ template SplayTree::SplayTree( const SplayTree & rhs ) : ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND ) { nullNode = new BinaryNode; nullNode->left = nullNode->right = nullNode; nullNode->element = ITEM_NOT_FOUND; root = nullNode; *this = rhs; } /** * Destructor. */ template SplayTree::~SplayTree( ) { makeEmpty( ); delete nullNode; } /** * Insert x into the tree. */ 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 return; } newNode = NULL; // So next insert will call new } /** * Remove x from 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 ) return; // Item not found; do nothing 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; } /** * 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 or ITEM_NOT_FOUND if empty. */ template const Comparable & SplayTree::findMin( ) { if( isEmpty( ) ) return ITEM_NOT_FOUND; BinaryNode *ptr = root; while( ptr->left != nullNode ) ptr = ptr->left; splay( ptr->element, root ); return ptr->element; } /** * 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 or ITEM_NOT_FOUND if empty. */ template const Comparable & SplayTree::findMax( ) { if( isEmpty( ) ) return ITEM_NOT_FOUND; BinaryNode *ptr = root; while( ptr->right != nullNode ) ptr = ptr->right; splay( ptr->element, root ); return ptr->element; } /** * Find item x in the tree. * Return the matching item or ITEM_NOT_FOUND if not found. */ template const Comparable & SplayTree::find( const Comparable & x ) { if( isEmpty( ) ) return ITEM_NOT_FOUND; splay( x, root ); if( root->element != x ) return ITEM_NOT_FOUND; return root->element; } /** * Make the tree logically empty. */ template void SplayTree::makeEmpty( ) { /****************************** * Comment this out, because it is prone to excessive * recursion on degenerate trees. Use alternate algorithm. reclaimMemory( root ); root = nullNode; *******************************/ 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; } /** * Print the tree contents in sorted order. */ template void SplayTree::printTree( ) const { if( isEmpty( ) ) cout << "Empty tree" << endl; else printTree( root ); } /** * 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. * This method may be overridden to use a different * splaying algorithm, however, the splay tree code * depends on the accessed item going to the 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 print a subtree t in sorted order. * WARNING: This is prone to running out of stack space. */ template void SplayTree::printTree( BinaryNode *t ) const { if( t != t->left ) { printTree( t->left ); cout << t->element << endl; printTree( t->right ); } } /** * 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 ) ); }