SplayTree.cpp - Implementation for top-down splay tree
	
	#include <iostream.h>
        #include "SplayTree.h"

        /**
         * Construct the tree.
         */
        template <class Comparable>
        SplayTree<Comparable>::SplayTree( const Comparable & notFound )
          : ITEM_NOT_FOUND( notFound )
        {
            nullNode = new BinaryNode<Comparable>;
            nullNode->left = nullNode->right = nullNode;
            nullNode->element = notFound;
            root = nullNode;
        }

        /**
         * Copy constructor.
         */
        template <class Comparable>
        SplayTree<Comparable>::SplayTree( const SplayTree<Comparable> & rhs )
          : ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND )
        {
            nullNode = new BinaryNode<Comparable>;
            nullNode->left = nullNode->right = nullNode;
            nullNode->element = ITEM_NOT_FOUND;
            root = nullNode;
            *this = rhs;
        }

        /**
         * Destructor.
         */
        template <class Comparable>
        SplayTree<Comparable>::~SplayTree( )
        {
            makeEmpty( );
            delete nullNode;
        }

        /**
         * Insert x into the tree.
         */
        template <class Comparable>
        void SplayTree<Comparable>::insert( const Comparable & x )
        {
            static BinaryNode<Comparable> *newNode = NULL;

            if( newNode == NULL )
                newNode = new BinaryNode<Comparable>;
            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 <class Comparable>
        void SplayTree<Comparable>::remove( const Comparable & x )
        {
            BinaryNode<Comparable> *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 <class Comparable>
        const Comparable & SplayTree<Comparable>::findMin( )
        {
            if( isEmpty( ) )
                return ITEM_NOT_FOUND;

            BinaryNode<Comparable> *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 <class Comparable>
        const Comparable & SplayTree<Comparable>::findMax( )
        {
            if( isEmpty( ) )
                return ITEM_NOT_FOUND;

            BinaryNode<Comparable> *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 <class Comparable>
        const Comparable & SplayTree<Comparable>::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 <class Comparable>
        void SplayTree<Comparable>::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 <class Comparable>
        bool SplayTree<Comparable>::isEmpty( ) const
        {
            return root == nullNode;
        }

        /**
         * Print the tree contents in sorted order.
         */
        template <class Comparable>
        void SplayTree<Comparable>::printTree( ) const
        {
            if( isEmpty( ) )
                cout << "Empty tree" << endl;
            else
                printTree( root );
        }

        /**
         * Deep copy.
         */
        template <class Comparable>
        const SplayTree<Comparable> &
        SplayTree<Comparable>::operator=( const SplayTree<Comparable> & 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 <class Comparable>
        void SplayTree<Comparable>::splay( const Comparable & x,
                                           BinaryNode<Comparable> * & t ) const
        {
            BinaryNode<Comparable> *leftTreeMax, *rightTreeMin;
            static BinaryNode<Comparable> 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 <class Comparable>
        void SplayTree<Comparable>::rotateWithLeftChild( BinaryNode<Comparable> * & k2 ) const
        {
            BinaryNode<Comparable> *k1 = k2->left;
            k2->left = k1->right;
            k1->right = k2;
            k2 = k1;
        }

        /**
         * Rotate binary tree node with right child.
         */
        template <class Comparable>
        void SplayTree<Comparable>::rotateWithRightChild( BinaryNode<Comparable> * & k1 ) const
        {
            BinaryNode<Comparable> *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 <class Comparable>
        void SplayTree<Comparable>::printTree( BinaryNode<Comparable> *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 <class Comparable>
        void SplayTree<Comparable>::reclaimMemory( BinaryNode<Comparable> * 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 <class Comparable>
        BinaryNode<Comparable> *
        SplayTree<Comparable>::clone( BinaryNode<Comparable> * t ) const
        {
            if( t == t->left )  // Cannot test against nullNode!!!
                return nullNode;
            else
                return new BinaryNode<Comparable>( t->element, clone( t->left ), clone( t->right ) );
        }
