Cod sursa(job #1182517)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 6 mai 2014 18:56:32
Problema Hashuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 13.87 kb
#include <cstdio>
#include <set>
#include <cstdlib>
#include <ctime>

using namespace std;

        #ifndef RED_BLACK_TREE_H_
        #define RED_BLACK_TREE_H_

        #include <iostream>       // For NULL

        // Red-black tree class
        //
        // CONSTRUCTION: with negative infinity object also
        //               used to signal failed finds
        //
        // ******************PUBLIC OPERATIONS*********************
        // void insert( x )       --> Insert x
        // void remove( x )       --> Remove x (unimplemented)
        // Comparable find( x )   --> Return item that matches x
        // Comparable findMin( )  --> Return smallest item
        // Comparable findMax( )  --> Return largest item
        // boolean isEmpty( )     --> Return true if empty; else false
        // void makeEmpty( )      --> Remove all items
        // void printTree( )      --> Print tree in sorted order



          // Node and forward declaration because g++ does
          // not understand nested classes.
        template <class Comparable>
        class RedBlackTree;

        template <class Comparable>
        class RedBlackNode
        {
            Comparable    element;
            RedBlackNode *left;
            RedBlackNode *right;
            int           color;

            // c = 1 should be c = RedBlackTree<Comparable>::BLACK
            // But Visual 5.0 does not comprehend it.
            RedBlackNode( const Comparable & theElement = Comparable( ),
                              RedBlackNode *lt = NULL, RedBlackNode *rt = NULL,
                              int c = 1 )
              : element( theElement ), left( lt ), right( rt ), color( c ) { }
            friend class RedBlackTree<Comparable>;
        };

        template <class Comparable>
        class RedBlackTree
        {
          public:
            explicit RedBlackTree( const Comparable & negInf );
            RedBlackTree( const RedBlackTree & rhs );
            ~RedBlackTree( );

            const Comparable & findMin( ) const;
            const Comparable & findMax( ) const;
            const Comparable & find( const Comparable & x ) const;
            bool isEmpty( ) const;
            void printTree( ) const;

            void makeEmpty( );
            void insert( const Comparable & x );
            void remove( const Comparable & x );

            enum { RED, BLACK };

            const RedBlackTree & operator=( const RedBlackTree & rhs );

          private:
            RedBlackNode<Comparable> *header;   // The tree header (contains negInf)
            const Comparable ITEM_NOT_FOUND;
            RedBlackNode<Comparable> *nullNode;

                // Used in insert routine and its helpers (logically static)
            RedBlackNode<Comparable> *current;
            RedBlackNode<Comparable> *parent;
            RedBlackNode<Comparable> *grand;
            RedBlackNode<Comparable> *great;

                // Usual recursive stuff
            void reclaimMemory( RedBlackNode<Comparable> *t ) const;
            void printTree( RedBlackNode<Comparable> *t ) const;
            RedBlackNode<Comparable> * clone( RedBlackNode<Comparable> * t ) const;

                // Red-black tree manipulations
            void handleReorient( const Comparable & item );
            RedBlackNode<Comparable> * rotate( const Comparable & item,
                                        RedBlackNode<Comparable> *parent ) const;
            void rotateWithLeftChild( RedBlackNode<Comparable> * & k2 ) const;
            void rotateWithRightChild( RedBlackNode<Comparable> * & k1 ) const;
        };

        #endif


        /**
         * Construct the tree.
         * negInf is a value less than or equal to all others.
         * It is also used as ITEM_NOT_FOUND.
         */
        template <class Comparable>
        RedBlackTree<Comparable>::RedBlackTree( const Comparable & negInf )
          : ITEM_NOT_FOUND( negInf )
        {
            nullNode    = new RedBlackNode<Comparable>;
            nullNode->left = nullNode->right = nullNode;
            header      = new RedBlackNode<Comparable>( negInf );
            header->left = header->right = nullNode;
        }

        /**
         * Copy constructor.
         */
        template <class Comparable>
        RedBlackTree<Comparable>::RedBlackTree( const RedBlackTree<Comparable> & rhs )
          : ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND )
        {
            nullNode    = new RedBlackNode<Comparable>;
            nullNode->left = nullNode->right = nullNode;
            header      = new RedBlackNode<Comparable>( ITEM_NOT_FOUND );
            header->left = header->right = nullNode;
            *this = rhs;
        }

        /**
         * Destroy the tree.
         */
        template <class Comparable>
        RedBlackTree<Comparable>::~RedBlackTree( )
        {
            makeEmpty( );
            delete nullNode;
            delete header;
        }

        /**
         * Insert item x into the tree. Does nothing if x already present.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::insert( const Comparable & x )
        {
            current = parent = grand = header;
            nullNode->element = x;

            while( current->element != x )
            {
                great = grand; grand = parent; parent = current;
                current = x < current->element ?  current->left : current->right;

                    // Check if two red children; fix if so
                if( current->left->color == RED && current->right->color == RED )
                     handleReorient( x );
            }

                // Insertion fails if already present
            if( current != nullNode )
                return;
            current = new RedBlackNode<Comparable>( x, nullNode, nullNode );

                // Attach to parent
            if( x < parent->element )
                parent->left = current;
            else
                parent->right = current;
            handleReorient( x );
        }

        /**
         * Remove item x from the tree.
         * Not implemented in this version.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::remove( const Comparable & x )
        {
            cout << "Sorry, remove unimplemented; " << x <<
                 " still present" << endl;
        }

        /**
         * Find the smallest item  the tree.
         * Return the smallest item or ITEM_NOT_FOUND if empty.
         */
        template <class Comparable>
        const Comparable & RedBlackTree<Comparable>::findMin( ) const
        {
            if( isEmpty( ) )
                return ITEM_NOT_FOUND;

            RedBlackNode<Comparable> *itr = header->right;

            while( itr->left != nullNode )
                itr = itr->left;

            return itr->element;
        }

        /**
         * Find the largest item in the tree.
         * Return the largest item or ITEM_NOT_FOUND if empty.
         */
        template <class Comparable>
        const Comparable & RedBlackTree<Comparable>::findMax( ) const
        {
            if( isEmpty( ) )
                return ITEM_NOT_FOUND;

            RedBlackNode<Comparable> *itr = header->right;

            while( itr->right != nullNode )
                itr = itr->right;

            return itr->element;
        }

        /**
         * Find item x in the tree.
         * Return the matching item or ITEM_NOT_FOUND if not found.
         */
        template <class Comparable>
        const Comparable & RedBlackTree<Comparable>::find( const Comparable & x ) const
        {
            nullNode->element = x;
            RedBlackNode<Comparable> *curr = header->right;

            for( ; ; )
            {
                if( x < curr->element )
                    curr = curr->left;
                else if( curr->element < x )
                    curr = curr->right;
                else if( curr != nullNode )
                    return curr->element;
                else
                    return ITEM_NOT_FOUND;
            }
        }

        /**
         * Make the tree logically empty.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::makeEmpty( )
        {
            reclaimMemory( header->right );
            header->right = nullNode;
        }

        /**
         * Test if the tree is logically empty.
         * Return true if empty, false otherwise.
         */
        template <class Comparable>
        bool RedBlackTree<Comparable>::isEmpty( ) const
        {
            return header->right == nullNode;
        }

        /**
         * Print the tree contents in sorted order.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::printTree( ) const
        {
            if( header->right == nullNode )
                cout << "Empty tree" << endl;
            else
                printTree( header->right );
        }


        /**
         * Deep copy.
         */
        template <class Comparable>
        const RedBlackTree<Comparable> &
        RedBlackTree<Comparable>::operator=( const RedBlackTree<Comparable> & rhs )
        {
            if( this != &rhs )
            {
                makeEmpty( );
                header->right = clone( rhs.header->right );
            }

            return *this;
        }

        /**
         * Internal method to print a subtree t in sorted order.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::printTree( RedBlackNode<Comparable> *t ) const
        {
            if( t != t->left )
            {
                printTree( t->left );
                cout << t->element << endl;
                printTree( t->right );
            }
        }

        /**
         * Internal method to clone subtree.
         */
        template <class Comparable>
        RedBlackNode<Comparable> *
        RedBlackTree<Comparable>::clone( RedBlackNode<Comparable> * t ) const
        {
            if( t == t->left )  // Cannot test against nullNode!!!
                return nullNode;
            else
                return new RedBlackNode<Comparable>( t->element, clone( t->left ),
                                               clone( t->right ), t->color );
        }


        /**
         * Internal routine that is called during an insertion
         *     if a node has two red children. Performs flip
         *     and rotatons.
         * item is the item being inserted.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::handleReorient( const Comparable & item )
        {
                // Do the color flip
            current->color = RED;
            current->left->color = BLACK;
            current->right->color = BLACK;

            if( parent->color == RED )   // Have to rotate
            {
                grand->color = RED;
                if( item < grand->element != item < parent->element )
                    parent = rotate( item, grand );  // Start dbl rotate
                current = rotate( item, great );
                current->color = BLACK;
            }
            header->right->color = BLACK; // Make root black
        }

        /**
         * Internal routine that performs a single or double rotation.
         * Because the result is attached to the parent, there are four cases.
         * Called by handleReorient.
         * item is the item in handleReorient.
         * parent is the parent of the root of the rotated subtree.
         * Return the root of the rotated subtree.
         */
        template <class Comparable>
        RedBlackNode<Comparable> *
        RedBlackTree<Comparable>::rotate( const Comparable & item,
                              RedBlackNode<Comparable> *theParent ) const
        {
            if( item < theParent->element )
            {
                item < theParent->left->element ?
                    rotateWithLeftChild( theParent->left )  :  // LL
                    rotateWithRightChild( theParent->left ) ;  // LR
                return theParent->left;
            }
            else
            {
                item < theParent->right->element ?
                    rotateWithLeftChild( theParent->right ) :  // RL
                    rotateWithRightChild( theParent->right );  // RR
                return theParent->right;
            }
        }

        /**
         * Rotate binary tree node with left child.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::
        rotateWithLeftChild( RedBlackNode<Comparable> * & k2 ) const
        {
            RedBlackNode<Comparable> *k1 = k2->left;
            k2->left = k1->right;
            k1->right = k2;
            k2 = k1;
        }

        /**
         * Rotate binary tree node with right child.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::
        rotateWithRightChild( RedBlackNode<Comparable> * & k1 ) const
        {
            RedBlackNode<Comparable> *k2 = k1->right;
            k1->right = k2->left;
            k2->left = k1;
            k1 = k2;
        }


        /**
         * Internal method to reclaim internal nodes
         * in subtree t.
         */
        template <class Comparable>
        void RedBlackTree<Comparable>::reclaimMemory( RedBlackNode<Comparable> *t ) const
        {
            if( t != t->left )
            {
                reclaimMemory( t->left );
                reclaimMemory( t->right );
                delete t;
            }
        }



int N, NR;

int main()
{
    srand( time( NULL ) );

    freopen("hashuri.in", "r", stdin);
    freopen("hashuri.out", "w", stdout);

    int i, tip, x;

    const int ITEM_NOT_FOUND = -999999999;
    RedBlackTree<int> TR( ITEM_NOT_FOUND );

    scanf("%d ", &N);

    for (i = 1; i <= N; i++)
    {
        scanf("%d %d ", &tip, &x);

        if (tip == 1 && TR.find( x ) == ITEM_NOT_FOUND ) TR.insert( x );
        if (tip == 2) TR.remove(x);
        if (tip == 3) printf("%d\n", TR.find(x) != ITEM_NOT_FOUND);
    }

    return 0;
}