Implement the avl tree, rbtree without the two fields: parent pointer and balance/color

#ifndef GYM_BINARY_SEARCH_TREE_COMMON_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4
#define GYM_BINARY_SEARCH_TREE_COMMON_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4

#include <stdint.h>
#include <assert.h>
#include <boost/call_traits.hpp>
#include <vector>
#include <stack>
#include <queue>

namespace pratique
{
    namespace details
    {
        enum child_position
        {
            left_child = 0,
            right_child = 1,
            child_position_limit = 2
        };

        enum search_result
        {
            empty_tree = 1,
            found_node = 2,
            should_insert_as_left = 4,
            should_insert_as_right = 8
        };

        template <typename TreeNodeIndicator>
        size_t height( TreeNodeIndicator root )
        {
            size_t h = 0;
            if ( root.is_non_null( ) ) {
                size_t lh = height<TreeNodeIndicator>( root.get_pointer( )->m_left ), rh = height<TreeNodeIndicator>( root.get_pointer( )->m_right );
                h = ( lh < rh ? rh : lh ) + 1;
            }
            return h;
        }

        template <typename TreeNodeIndicator>
        bool has_filiation(
            TreeNodeIndicator parent,
            TreeNodeIndicator child
        )
        {
            return parent.get_pointer( )->m_left == child || parent.get_pointer( )->m_right == child;
        }

        template <typename TreeNodeIndicator>
        TreeNodeIndicator * get_minimum_child(
            TreeNodeIndicator * parent,
            std::vector<TreeNodeIndicator *> & ancestors
        )
        {
            assert( parent != NULL && parent->is_non_null( ) && parent->get_pointer( )->m_right.is_non_null( ) );
            ancestors.push_back( parent );
            TreeNodeIndicator * minimum_child = &parent->get_pointer( )->m_right;
            while ( minimum_child->get_pointer( )->m_left.is_non_null( ) ) {
                ancestors.push_back( minimum_child );
                minimum_child = &minimum_child->get_pointer( )->m_left;
            }
            return minimum_child;
        }

        template <typename TreeNodeIndicator>
        TreeNodeIndicator * get_other_child(
            TreeNodeIndicator parent,
            TreeNodeIndicator child
        )
        {
            TreeNodeIndicator * another_child = &parent.get_pointer( )->m_left;
            if ( *another_child == child ) {
                another_child = &parent.get_pointer( )->m_right;
            }
            return another_child;
        }

        template <typename TreeNodeIndicator>
        TreeNodeIndicator * get_other_child(
            TreeNodeIndicator parent,
            child_position this_child_position
        )
        {
            return this_child_position == left_child ? &parent.get_pointer( )->m_right : &parent.get_pointer( )->m_left;
        }

        template <typename TreeNodeIndicator>
        child_position get_child_position(
            TreeNodeIndicator parent,
            TreeNodeIndicator child
        )
        {
            child_position cp = left_child;
            if ( parent.get_pointer( )->m_right == child ) {
                cp = right_child;
            }
            return cp;
        }

        template <typename TreeNodeIndicator>
        bool in_the_same_branch(
            TreeNodeIndicator grandparent,
            TreeNodeIndicator parent,
            TreeNodeIndicator child
        )
        {
            return (
                ( grandparent.get_pointer( )->m_left == parent && parent.get_pointer( )->m_left == child ) ||
                ( grandparent.get_pointer( )->m_right == parent && parent.get_pointer( )->m_right == child )
            );
        }

        template <typename TreeNodeIndicator>
        TreeNodeIndicator * pop_without_doubt(
            std::stack<TreeNodeIndicator *> & ancestors
        )
        {
            assert( !ancestors.empty( ) );
            TreeNodeIndicator * parent = ancestors.top( );
            ancestors.pop( );
            return parent;
        }

        template <typename TreeNodeIndicator>
        TreeNodeIndicator * pop(
            std::stack<TreeNodeIndicator *> & ancestors
        )
        {
            TreeNodeIndicator * parent = NULL;
            if ( !ancestors.empty( ) ) {
                parent = pop_without_doubt( ancestors );
            }
            return parent;
        }

        template <typename T, typename TreeNodeIndicator>
        search_result find(
            TreeNodeIndicator const * const root,
            typename boost::call_traits<T>::param_type t,
            std::stack<TreeNodeIndicator *> * ancestors,
            TreeNodeIndicator ** n
        )
        {
            search_result sr = empty_tree;
            if ( n != NULL && *n != NULL ) {
                ( *n )->pointer = NULL;
            }
            TreeNodeIndicator * node = const_cast<TreeNodeIndicator *>( root );
            if ( node->is_non_null( ) ) {
                if ( !node->value_equals( t ) ) {
                    for (
                        TreeNodeIndicator * p = node, *c = p;
                        c->is_non_null( );
                        ancestors != NULL ? ( ancestors->push( p ), 0 ) : 0
                    ) {
                        p = c;
                        if ( c->value( ) > t ) {
                            c = &p->get_pointer( )->m_left;
                            sr = should_insert_as_left;
                        } else if ( c->value( ) < t ) {
                            c = &p->get_pointer( )->m_right;
                            sr = should_insert_as_right;
                        } else {
                            if ( n != NULL ) {
                                *n = c;
                            }
                            sr = found_node;
                            break;
                        }
                    }
                } else {
                    if ( n != NULL ) {
                        *n = node;
                    }
                    sr = found_node;
                }
            }
            return sr;
        }

        template <typename TreeNodeIndicator, typename Visitor>
        void levelorder_visit( TreeNodeIndicator const root, Visitor visitor )
        {
            TreeNodeIndicator dummy;
            if ( root.is_non_null( ) ) {
                std::queue<TreeNodeIndicator const> q1, q2, *pq1 = &q1, *pq2 = &q2;
                q1.push( root );
                visitor( dummy );
                while ( !pq1->empty( ) ) {
                    while ( !pq1->empty( ) ) {
                        TreeNodeIndicator n = pq1->front( );
                        visitor( n );
                        pq1->pop( );
                        if ( n.get_pointer( )->m_left.is_non_null( ) ) {
                            pq2->push( n.get_pointer( )->m_left );
                        }
                        if ( n.get_pointer( )->m_right.is_non_null( ) ) {
                            pq2->push( n.get_pointer( )->m_right );
                        }
                    }
                    visitor( dummy );
                    std::swap( pq1, pq2 );
                }
            }
        }
    }
}

#endif //GYM_BINARY_SEARCH_TREE_COMMON_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4



#ifndef GYM_AVL_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4
#define GYM_AVL_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4

#include "bst_common.h"
#include <algorithm>

namespace pratique
{
    namespace details
    {
        template <typename T>
        struct avl_tree_node
        {
            typedef union child {
                avl_tree_node<T> * pointer;
                intptr_t           int_value;

                child( avl_tree_node<T> * p = NULL, int balance = 0 ) : pointer( p )
                {
                    set_balance( balance );
                }

                bool is_null() const { return pointer == NULL; }
                bool is_non_null() const { return int_value > 1; }

                int get_balance() const
                {
                    int balance = int_value & 3;
                    assert( balance <= 2 );
                    if ( balance == 2 ) {
                        balance = -1;
                    }
                    return balance;
                }
                void set_balance( int balance )
                {
                    assert( balance >= -1 && balance <= 1 );
                    if ( balance == -1 ) {
                        balance = 2;
                    }
                    int_value &= (~3);
                    int_value |= balance;
                #if ( defined( DEBUG ) || defined( _DEBUG ) || defined( DBG ) )
                    if ( is_null() ) {
                        assert(balance == 0);
                    }
                #endif
                }

                avl_tree_node<T> const * get_pointer() const
                {
                    return const_cast<avl_tree_node<T> const *>(
                        reinterpret_cast<avl_tree_node<T> *>( int_value & (~3) )
                    );
                }

                avl_tree_node<T> * get_pointer()
                {
                    return reinterpret_cast<avl_tree_node<T> *>( int_value & (~3) );
                }

                bool value_equals( typename boost::call_traits<T>::param_type t ) const
                {
                    return is_non_null() && ( get_pointer()->m_data == t );
                }
                T const & value() const { assert( is_non_null() ); return get_pointer()->m_data; }
                T & value() { assert( is_non_null() ); return get_pointer()->m_data; }

                bool operator==( typename boost::call_traits<child>::param_type c ) const
                {
                    return int_value == c.int_value;
                }

                bool operator!=( typename boost::call_traits<child>::param_type c ) const
                {
                    return int_value != c.int_value;
                }
            } child_t;

            struct hash
            {
                size_t operator()( child_t const c ) const
                {
                    return std::hash<intptr_t>()( c.int_value );
                }
            };

            T m_data;
            child_t m_left, m_right;

            avl_tree_node() : m_left{ NULL, false }, m_right{ NULL, false } {}
            avl_tree_node( typename boost::call_traits<T>::param_type t ) : m_data{ t }, m_left{ NULL, false }, m_right{ NULL, false } {}
        };

        template <typename T>
        bool check_balance_attributes( typename avl_tree_node<T>::child_t const root )
        {
            bool passed = true;
            if ( root.is_non_null( ) ) {
                auto left = root.get_pointer( )->m_left, right = root.get_pointer( )->m_right;
                int diff = static_cast<int>( height( left ) ) - static_cast<int>( height( right ) );
                passed = ( diff >= -1 && diff <= 1 ) && ( root.get_balance( ) == diff );
                if ( passed ) {
                    passed = check_balance_attributes<T>( left ) && check_balance_attributes<T>( right );
                }
            }
            return passed;
        }

        template <typename T>
        bool is_avl_tree( typename avl_tree_node<T>::child_t const root )
        {
            return check_balance_attributes<T>( root );
        }
    }

    template <typename T>
    class avl_tree
    {
        typename details::avl_tree_node<T>::child_t m_root;

        inline typename details::avl_tree_node<T>::child_t * reset_parent(
            typename details::avl_tree_node<T>::child_t * grandparent,
            typename details::avl_tree_node<T>::child_t new_parent,
            details::child_position pcp
        ) {
            typename details::avl_tree_node<T>::child_t * pointer_to_new_parent = NULL;
            if ( grandparent != NULL ) {
                if ( pcp == details::left_child ) {
                    grandparent->get_pointer()->m_left = new_parent;
                    pointer_to_new_parent = &grandparent->get_pointer()->m_left;
                } else {
                    grandparent->get_pointer()->m_right = new_parent;
                    pointer_to_new_parent = &grandparent->get_pointer()->m_right;
                }
            } else {
                m_root = new_parent;
                pointer_to_new_parent = &m_root;
            }
            return pointer_to_new_parent;
        }

        inline typename details::avl_tree_node<T>::child_t * left_rotate(
            typename details::avl_tree_node<T>::child_t * grandparent,
            typename details::avl_tree_node<T>::child_t parent,
            typename details::avl_tree_node<T>::child_t child,
            int parent_balance = 0,
            int child_balance = 0
        )
        {
            assert( grandparent == NULL || details::has_filiation( *grandparent, parent ) );
            assert( details::has_filiation( parent, child ) );
            details::child_position pcp = details::left_child;
            if ( grandparent != NULL ) {
                pcp = details::get_child_position( *grandparent, parent );
            }
            parent.set_balance( parent_balance );
            child.set_balance( child_balance );
            parent.get_pointer()->m_left = child.get_pointer()->m_right;
            child.get_pointer()->m_right = parent;
            return reset_parent( grandparent, child, pcp );
        }

        inline typename details::avl_tree_node<T>::child_t * right_rotate(
            typename details::avl_tree_node<T>::child_t * grandparent,
            typename details::avl_tree_node<T>::child_t parent,
            typename details::avl_tree_node<T>::child_t child,
            int parent_balance = 0,
            int child_balance = 0
        )
        {
            assert( grandparent == NULL || details::has_filiation( *grandparent, parent ) );
            assert( details::has_filiation( parent, child ) );
            details::child_position pcp = details::left_child;
            if ( grandparent != NULL ) {
                pcp = details::get_child_position( *grandparent, parent );
            }
            parent.set_balance( parent_balance );
            child.set_balance( child_balance );
            parent.get_pointer()->m_right = child.get_pointer()->m_left;
            child.get_pointer()->m_left = parent;
            return reset_parent( grandparent, child, pcp );
        }

        inline typename details::avl_tree_node<T>::child_t * left_rotate(
            typename details::avl_tree_node<T>::child_t * new_grandparent,
            typename details::avl_tree_node<T>::child_t grandparent,
            typename details::avl_tree_node<T>::child_t parent,
            typename details::avl_tree_node<T>::child_t child
        )
        {
            int child_balance = child.get_balance();
            assert( new_grandparent == NULL || details::has_filiation( *new_grandparent, grandparent ) );
            assert( details::has_filiation( grandparent, parent ) );
            assert( details::has_filiation( parent, child ) );
            details::child_position gcp = details::left_child;
            if ( new_grandparent != NULL ) {
                gcp = details::get_child_position( *new_grandparent, grandparent );
            }
            if ( child_balance == -1 ) {
                grandparent.set_balance( 0 );
                parent.set_balance( 1 );
            }
            else if ( child_balance == 1 ) {
                grandparent.set_balance( -1 );
                parent.set_balance( 0 );
            }
            else {
                grandparent.set_balance( 0 );
                parent.set_balance( 0 );
            }
            child.set_balance( 0 );
            parent.get_pointer()->m_right = child.get_pointer()->m_left;
            child.get_pointer()->m_left = parent;
            grandparent.get_pointer()->m_left = child.get_pointer()->m_right;
            child.get_pointer()->m_right = grandparent;
            return reset_parent( new_grandparent, child, gcp );
        }

        inline typename details::avl_tree_node<T>::child_t * right_rotate(
            typename details::avl_tree_node<T>::child_t * new_grandparent,
            typename details::avl_tree_node<T>::child_t grandparent,
            typename details::avl_tree_node<T>::child_t parent,
            typename details::avl_tree_node<T>::child_t child
        )
        {
            int child_balance = child.get_balance();
            assert( new_grandparent == NULL || details::has_filiation( *new_grandparent, grandparent ) );
            assert( details::has_filiation( grandparent, parent ) );
            assert( details::has_filiation( parent, child ) );
            details::child_position gcp = details::left_child;
            if ( new_grandparent != NULL ) {
                gcp = details::get_child_position( *new_grandparent, grandparent );
            }
            if ( child_balance == -1 ) {
                grandparent.set_balance( 1 );
                parent.set_balance( 0 );
            }
            else if ( child_balance == 1 ) {
                grandparent.set_balance( 0 );
                parent.set_balance( -1 );
            }
            else {
                grandparent.set_balance( 0 );
                parent.set_balance( 0 );
            }
            child.set_balance( 0 );
            parent.get_pointer()->m_left = child.get_pointer()->m_right;
            child.get_pointer()->m_right = parent;
            grandparent.get_pointer()->m_right = child.get_pointer()->m_left;
            child.get_pointer()->m_left = grandparent;
            return reset_parent( new_grandparent, child, gcp );
        }

        void insertion_rebalance(
            typename details::avl_tree_node<T>::child_t * child,
            std::stack<typename details::avl_tree_node<T>::child_t *> & ancestors
        )
        {
            assert( child != NULL && child->is_non_null() && !ancestors.empty() );
            for (
                typename details::avl_tree_node<T>::child_t * parent = details::pop_without_doubt( ancestors );
                parent != NULL;
                parent = details::pop( ancestors )
            ) {
                assert( details::has_filiation( *parent, *child ) );
                details::child_position ccp = details::get_child_position( *parent, *child );
                int parent_balance = parent->get_balance();
                assert( parent_balance >= -1 && parent_balance <= 1 );
                if ( ccp == details::left_child ) {
                    if ( parent_balance == -1 ) {
                        parent->set_balance( 0 );
                        break;
                    }
                    else if ( parent_balance == 0 ) {
                        parent->set_balance( 1 );
                        child = parent;
                    }
                    else {
                        assert( parent_balance == 1 );
                        typename details::avl_tree_node<T>::child_t * grandparent = NULL;
                        if ( !ancestors.empty() ) {
                            grandparent = ancestors.top();
                            assert( details::has_filiation( *grandparent, *parent ) );
                        }

                        int child_balance = child->get_balance();
                        if ( child_balance == -1 ) {
                            left_rotate( grandparent, *parent, *child, child->get_pointer()->m_right );
                            break;
                        }
                        else if ( child_balance == 0 ) {
                            child = left_rotate( grandparent, *parent, *child, 1, -1 );
                        }
                        else {
                            assert( child_balance == 1 );
                            left_rotate( grandparent, *parent, *child );
                            break;
                        }
                    }
                }
                else {
                    if ( parent_balance == -1 ) {
                        typename details::avl_tree_node<T>::child_t * grandparent = NULL;
                        if ( !ancestors.empty() ) {
                            grandparent = ancestors.top();
                            assert( details::has_filiation( *grandparent, *parent ) );
                        }

                        int child_balance = child->get_balance();
                        if ( child_balance == -1 ) {
                            right_rotate( grandparent, *parent, *child );
                            break;
                        }
                        else if ( child_balance == 0 ) {
                            child = right_rotate( grandparent, *parent, *child, -1, 1 );
                        }
                        else {
                            assert( child_balance == 1 );
                            right_rotate( grandparent, *parent, *child, child->get_pointer()->m_left );
                            break;
                        }
                    }
                    else if ( parent_balance == 0 ) {
                        parent->set_balance( -1 );
                        child = parent;
                    }
                    else {
                        parent->set_balance( 0 );
                        break;
                    }
                }
            }
        }

        typename details::avl_tree_node<T>::child_t * transplant(
            typename details::avl_tree_node<T>::child_t expellee_parent,
            typename details::avl_tree_node<T>::child_t expellee,
            typename details::avl_tree_node<T>::child_t replacer
        )
        {
            assert( details::has_filiation( expellee_parent, expellee ) );
            assert( !expellee.is_null() );
            if ( !replacer.is_null() ) {
                if ( !details::has_filiation( expellee, replacer ) ) {
                    replacer.get_pointer()->m_left  = expellee.get_pointer()->m_left;
                    replacer.get_pointer()->m_right = expellee.get_pointer()->m_right;
                    replacer.set_balance( expellee.get_balance() );
                }
                else {
                    if ( expellee.get_pointer()->m_left == replacer ) {
                        replacer.get_pointer()->m_right = expellee.get_pointer()->m_right;
                        assert( replacer.get_pointer()->m_left.is_null() );
                        replacer.set_balance( expellee.get_balance() - 1 );
                    }
                    else {
                        replacer.get_pointer()->m_left = expellee.get_pointer()->m_left;
                        assert( replacer.get_pointer()->m_right.is_null() );
                        replacer.set_balance( expellee.get_balance() + 1 );
                    }
                }
            }
            typename details::avl_tree_node<T>::child_t * new_child;
            auto ecp = details::get_child_position( expellee_parent, expellee );
            if ( ecp == details::left_child ) {
                expellee_parent.get_pointer()->m_left = replacer;
                new_child = &expellee_parent.get_pointer()->m_left;
            }
            else {
                expellee_parent.get_pointer()->m_right = replacer;
                new_child = &expellee_parent.get_pointer()->m_right;
            }
            if ( m_root == expellee ) {
                m_root = *new_child;
            }
            return new_child;
        }

        void erasing_rebalance(
            typename details::avl_tree_node<T>::child_t * replacement,
            details::child_position rcp,
            std::stack<typename details::avl_tree_node<T>::child_t *> & ancestors
        )
        {
            while ( !ancestors.empty() ) {
                typename details::avl_tree_node<T>::child_t * parent = details::pop_without_doubt( ancestors ), * grandparent = NULL;
                assert( details::has_filiation( *parent, *replacement ) );

                details::child_position pcp = details::left_child;
                if ( !ancestors.empty() ) {
                    grandparent = ancestors.top();
                    pcp = details::get_child_position( *grandparent, *parent );
                    parent = &grandparent->get_pointer()->m_left;
                    if ( pcp == details::right_child ) {
                        parent = &grandparent->get_pointer()->m_right;
                    }
                }
                else {
                    parent = &m_root;
                }

                int parent_balance = parent->get_balance();
                assert( parent_balance >= -1 && parent_balance <= 1 );
                if ( rcp == details::left_child ) {
                    if ( parent_balance == -1 ) {
                        typename details::avl_tree_node<T>::child_t * sibling = details::get_other_child( *parent, rcp );
                        int sibling_balance = sibling->get_balance();
                        if ( sibling_balance == -1 ) {
                            right_rotate( grandparent, *parent, *sibling );
                        }
                        else if ( sibling_balance == 0 ) {
                            right_rotate( grandparent, *parent, *sibling, -1, 1 );
                            break;
                        }
                        else {
                            assert( sibling_balance == 1 );
                            right_rotate( grandparent, *parent, *sibling, sibling->get_pointer()->m_left );
                        }
                        if ( grandparent != NULL ) {
                            rcp = details::left_child;
                            replacement = &grandparent->get_pointer()->m_left;
                            if ( pcp == details::right_child ) {
                                rcp = details::right_child;
                                replacement = &grandparent->get_pointer()->m_right;
                            }
                        }
                    }
                    else if ( parent_balance == 0 ) {
                        parent->set_balance( -1 );
                        break;
                    }
                    else {
                        assert( parent_balance == 1 );
                        parent->set_balance( 0 );
                        replacement = parent;
                        if ( !ancestors.empty() ) {
                            rcp = details::get_child_position( *ancestors.top(), *replacement );
                        }
                    }
                }
                else {
                    if ( parent_balance == -1 ) {
                        parent->set_balance( 0 );
                        replacement = parent;
                        if ( !ancestors.empty() ) {
                            rcp = details::get_child_position( *ancestors.top(), *replacement );
                        }
                    }
                    else if ( parent_balance == 0 ) {
                        parent->set_balance( 1 );
                        break;
                    }
                    else {
                        assert( parent_balance == 1 );
                        typename details::avl_tree_node<T>::child_t * sibling = details::get_other_child( *parent, rcp );
                        int sibling_balance = sibling->get_balance();
                        if ( sibling_balance == -1 ) {
                            left_rotate( grandparent, *parent, *sibling, sibling->get_pointer()->m_right );
                        }
                        else if ( sibling_balance == 0 ) {
                            left_rotate( grandparent, *parent, *sibling, 1, -1 );
                            break;
                        }
                        else {
                            assert( sibling_balance == 1 );
                            left_rotate( grandparent, *parent, *sibling );
                        }
                        if ( grandparent != NULL ) {
                            rcp = details::left_child;
                            replacement = &grandparent->get_pointer()->m_left;
                            if ( pcp == details::right_child ) {
                                rcp = details::right_child;
                                replacement = &grandparent->get_pointer()->m_right;
                            }
                        }
                    }
                }
            }
        }
    public:
        avl_tree() {}
        avl_tree( avl_tree<T> const & );
        avl_tree<T> & operator=( avl_tree<T> const & );

        void insert( typename boost::call_traits<T>::param_type t )
        {
            assert( details::is_avl_tree<T>( m_root ) );
            std::stack<typename details::avl_tree_node<T>::child_t *> ancestors;
            typename details::avl_tree_node<T>::child_t * child = NULL;
            details::search_result sr = details::find<T>( &m_root, t, &ancestors, &child );
            if ( ( sr & ( details::empty_tree | details::should_insert_as_left | details::should_insert_as_right ) ) != 0 ) {
                details::avl_tree_node<T> * new_node = new details::avl_tree_node<T>( t );
                switch ( sr ) {
                case details::empty_tree:
                    assert( m_root.is_null() );
                    m_root.pointer = new_node;
                    return;
                case details::should_insert_as_left:
                    ancestors.top()->get_pointer()->m_left.pointer = new_node;
                    child = &ancestors.top()->get_pointer()->m_left;
                    break;
                case details::should_insert_as_right:
                    ancestors.top()->get_pointer()->m_right.pointer = new_node;
                    child = &ancestors.top()->get_pointer()->m_right;
                    break;
                default:
                    assert( false && "bug" );
                }
                insertion_rebalance( child, ancestors );
                assert( details::is_avl_tree<T>( m_root ) );
            }
        }

        void erase( typename boost::call_traits<T>::param_type t )
        {
            assert( details::is_avl_tree<T>( m_root ) );
            std::stack<typename details::avl_tree_node<T>::child_t *> ancestors;
            details::avl_tree_node<T> dummy_node;
            typename details::avl_tree_node<T>::child_t * expellee = NULL, dummy;
            auto result = details::find<T>( &m_root, t, &ancestors, &expellee );
            if ( result == details::found_node ) {
                details::child_position rcp;
                typename details::avl_tree_node<T>::child_t expellee_ref;
                typename details::avl_tree_node<T>::child_t * expellee_parent = NULL;
                if ( !ancestors.empty() ) {
                    expellee_parent = ancestors.top();
                }
                if ( expellee_parent == NULL ) {
                    assert( m_root == *expellee );
                    dummy_node.m_left = m_root;
                    dummy.pointer = &dummy_node;
                    expellee_parent = &dummy;
                }
                expellee_ref = *expellee;
                assert( expellee != NULL && expellee->is_non_null() );
                typename details::avl_tree_node<T>::child_t * replacement;
                if ( expellee->get_pointer()->m_right.is_non_null() ) {
                    std::vector<typename details::avl_tree_node<T>::child_t *> new_ancestors;
                    replacement = details::get_minimum_child( expellee, new_ancestors );
                    assert( replacement != NULL && replacement->is_non_null() );
                    assert( !new_ancestors.empty() );
                    assert( details::height( *replacement ) <= 2 );
                    auto replacement_ref = *replacement;
                    auto expellee_ref = *expellee;
                    rcp = details::get_child_position( *new_ancestors.back(), replacement_ref );
                    replacement = transplant( *new_ancestors.back(), replacement_ref, replacement_ref.get_pointer()->m_right );
                    expellee = transplant( *expellee_parent, expellee_ref, replacement_ref );
                    ancestors.push( expellee );
                    std::for_each(
                        new_ancestors.begin() + 1, new_ancestors.end(),
                        [ &ancestors ]( typename details::avl_tree_node<T>::child_t * node ) { ancestors.push( node ); }
                    );
                } else {
                    assert( details::height( *expellee ) <= 2 );
                    rcp = details::get_child_position( *expellee_parent, *expellee );
                    replacement = transplant( *expellee_parent, *expellee, expellee->get_pointer()->m_left );
                }
                erasing_rebalance( replacement, rcp, ancestors );
                delete expellee_ref.get_pointer();
                assert( details::is_avl_tree<T>( m_root ) );
            }
        }

        template <typename Visitor>
        void levelorder_visit( Visitor visitor ) const
        {
            details::levelorder_visit( m_root, visitor );
        }

        bool is_valid( ) const { return details::is_avl_tree<T>( m_root ); }
    };
}

#endif //GYM_AVL_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4


#ifndef GYM_RED_BLACK_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4
#define GYM_RED_BLACK_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4

#include "bst_common.h"
#include <algorithm>
#include <unordered_map>

namespace pratique
{
    namespace details
    {
        template <typename T>
        struct rbtree_node
        {
            typedef union child {
                rbtree_node<T> * pointer;
                intptr_t         int_value;

                child( rbtree_node<T> * p = NULL, bool red = false ) : pointer( p )
                {
                    if ( red ) {
                        set_red();
                    }
                }

                bool is_null() const { return pointer == NULL; }
                bool is_non_null() const { return int_value > 1; }
                bool is_red() const { assert( is_non_null() ); return ( int_value & 1 ) != 0; }
                bool is_black() const { return ( int_value & 1 ) == 0; }
                void set_red() { assert( is_non_null() ); int_value |= 1; }
                void set_black() { int_value &= ~1; }
                void set_color( bool red )
                {
                    if ( red ) { set_red(); } else { set_black(); }
                }

                rbtree_node<T> const * get_pointer() const
                {
                    rbtree_node<T> const * p = pointer;
                    if ( is_red() ) {
                        p = reinterpret_cast<rbtree_node<T> const *>( int_value & ~1 );
                    }
                    return p;
                }

                rbtree_node<T> * get_pointer()
                {
                    rbtree_node<T> * p = pointer;
                    if ( is_red() ) {
                        p = reinterpret_cast<rbtree_node<T> *>( int_value & ~1 );
                    }
                    return p;
                }

                bool value_equals( typename boost::call_traits<T>::param_type t ) const
                {
                    return is_non_null() && ( get_pointer()->m_data == t );
                }
                T const & value() const { assert( is_non_null() ); return get_pointer()->m_data; }
                T & value() { assert( is_non_null() ); return get_pointer()->m_data; }

                bool operator==( typename boost::call_traits<child>::param_type c ) const
                {
                    return int_value == c.int_value;
                }

                bool operator!=( typename boost::call_traits<child>::param_type c ) const
                {
                    return int_value != c.int_value;
                }
            } child_t;

            struct hash
            {
                size_t operator()( child_t const c ) const
                {
                    return std::hash<intptr_t>()( c.int_value );
                }
            };

            T m_data;
            child_t m_left, m_right;

            rbtree_node() : m_left{ NULL, false }, m_right{ NULL, false } {}
            rbtree_node( typename boost::call_traits<T>::param_type t ) : m_data{ t }, m_left{ NULL, false }, m_right{ NULL, false } {}
        };

        template <typename T>
        bool check_red_black_attributes( typename rbtree_node<T>::child_t const root )
        {
            bool passed = true;
            if ( root.is_non_null() ) {
                auto left = root.get_pointer()->m_left, right = root.get_pointer()->m_right;
                if ( root.is_red() ) {
                    passed = left.is_black() && right.is_black();
                }
                if ( passed ) {
                    passed = check_red_black_attributes<T>( left ) && check_red_black_attributes<T>( right );
                }
            }
            return passed;
        }

        template <typename T>
        bool compute_black_height(
            int starting_height,
            typename rbtree_node<T>::child_t const node,
            int & ending_height
        )
        {
            bool successful = true;
            ending_height = starting_height;
            if ( node.is_non_null() ) {
                if ( node.is_black() ) {
                    ++starting_height;
                }
                if ( node.get_pointer()->m_left.is_non_null() || node.get_pointer()->m_right.is_non_null() ) {
                    int left_height, right_height;
                    successful = (
                        compute_black_height<T>( starting_height, node.get_pointer()->m_left, left_height ) &&
                        compute_black_height<T>( starting_height, node.get_pointer()->m_right, right_height ) &&
                        left_height == right_height
                    );
                    if ( successful ) {
                        ending_height = left_height;
                    }
                }
                else {
                    ending_height = starting_height;
                }
            }
            return successful;
        }

        template <typename T>
        bool is_rb_tree( typename rbtree_node<T>::child_t const root )
        {
            int height = 0;
            return compute_black_height<T>( 0, root, height ) && root.is_black() && check_red_black_attributes<T>( root );
        }
    }

    // In fact what I implement is the 2-3-4-tree
    template <typename T>
    class rbtree
    {
        typename details::rbtree_node<T>::child_t m_root;

        void rebalance_nodes_in_the_different_branch(
            std::stack<typename details::rbtree_node<T>::child_t *> & ancestors,
            typename details::rbtree_node<T>::child_t ** parent,
            typename details::rbtree_node<T>::child_t ** child,
            details::child_position * ccp
        )
        {
            assert( details::has_filiation( **parent, **child ) );
            typename details::rbtree_node<T>::child_t * grandparent = ancestors.top();
            details::child_position pcp = details::get_child_position( *grandparent, **parent );
            *ccp = details::get_child_position( **parent, **child );
            if ( pcp != *ccp ) {
                typename details::rbtree_node<T>::child_t parent_ref = **parent;
                typename details::rbtree_node<T>::child_t child_ref = **child;
                if ( *ccp == details::left_child ) {
                    parent_ref.get_pointer()->m_left = child_ref.get_pointer()->m_right;
                    child_ref.get_pointer()->m_right = parent_ref;
                    grandparent->get_pointer()->m_right = child_ref;
                    *parent = &grandparent->get_pointer()->m_right;
                    *child = &( *parent )->get_pointer()->m_right;
                    *ccp = details::right_child;
                }
                else {
                    parent_ref.get_pointer()->m_right = child_ref.get_pointer()->m_left;
                    child_ref.get_pointer()->m_left = parent_ref;
                    grandparent->get_pointer()->m_left = child_ref;
                    *parent = &grandparent->get_pointer()->m_left;
                    *child = &( *parent )->get_pointer()->m_left;
                    *ccp = details::left_child;
                }
            }
        }

        void rebalance_nodes_in_the_same_branch(
            std::stack<typename details::rbtree_node<T>::child_t *> & ancestors,
            typename details::rbtree_node<T>::child_t * parent,
            typename details::rbtree_node<T>::child_t ** child,
            details::child_position ccp
        )
        {
            assert( !ancestors.empty() && details::has_filiation( *parent, **child ) );
            typename details::rbtree_node<T>::child_t * grandparent = details::pop_without_doubt( ancestors );
            typename details::rbtree_node<T>::child_t * new_grandparent = NULL;
            details::child_position gcp = details::left_child;
            if ( !ancestors.empty() ) {
                new_grandparent = ancestors.top();
                gcp = details::get_child_position( *new_grandparent, *grandparent );
            }

            auto parent_ref = *parent;
            if ( ccp == details::left_child ) {
                grandparent->get_pointer()->m_left = parent_ref.get_pointer()->m_right;
                parent_ref.get_pointer()->m_right = *grandparent;
            }
            else {
                grandparent->get_pointer()->m_right = parent_ref.get_pointer()->m_left;
                parent_ref.get_pointer()->m_left = *grandparent;
            }
            (*child)->set_black();
            if ( new_grandparent != NULL && new_grandparent->is_non_null() ) {
                if ( gcp == details::left_child ) {
                    new_grandparent->get_pointer()->m_left = parent_ref;
                    parent = &new_grandparent->get_pointer()->m_left;
                }
                else {
                    new_grandparent->get_pointer()->m_right = parent_ref;
                    parent = &new_grandparent->get_pointer()->m_right;
                }
            }
            else {
                m_root = parent_ref;
            }
            *child = parent;
        }

        void insertion_rebalance(
            typename details::rbtree_node<T>::child_t * child,
            std::stack<typename details::rbtree_node<T>::child_t *> & ancestors
        )
        {
            assert( child != NULL && child->is_non_null() && !ancestors.empty() );
            for ( typename details::rbtree_node<T>::child_t * parent = details::pop_without_doubt( ancestors ); parent != NULL; parent = details::pop( ancestors ) ) {
                assert( details::has_filiation( *parent, *child ) );
                typename details::rbtree_node<T>::child_t * sibling = details::get_other_child( *parent, *child );
                if ( !sibling->is_black() ) { // cannot call is_red()
                    child->set_black();
                    sibling->set_black();
                    child = parent;
                    child->set_red();
                }
                else {
                    if ( parent->is_red() && !ancestors.empty() ) {
                        details::child_position ccp;
                        rebalance_nodes_in_the_different_branch( ancestors, &parent, &child, &ccp );
                        rebalance_nodes_in_the_same_branch( ancestors, parent, &child, ccp );
                    }
                    else {
                        if ( ancestors.empty() ) {
                            m_root = *parent;
                        }
                        break;
                    }
                }
            }
        }

        typename details::rbtree_node<T>::child_t * transplant(
            typename details::rbtree_node<T>::child_t expellee_parent,
            typename details::rbtree_node<T>::child_t expellee,
            typename details::rbtree_node<T>::child_t replacer
        )
        {
            assert( details::has_filiation( expellee_parent, expellee ) );
            assert( !expellee.is_null() );
            if ( !replacer.is_null() ) {
                if ( !details::has_filiation( expellee, replacer ) ) {
                    replacer.get_pointer()->m_left  = expellee.get_pointer()->m_left;
                    replacer.get_pointer()->m_right = expellee.get_pointer()->m_right;
                }
                else {
                    if ( expellee.get_pointer()->m_left == replacer ) {
                        replacer.get_pointer()->m_right = expellee.get_pointer()->m_right;
                        assert( replacer.get_pointer()->m_left.is_null() );
                    }
                    else {
                        replacer.get_pointer()->m_left = expellee.get_pointer()->m_left;
                        assert( replacer.get_pointer()->m_right.is_null() );
                    }
                }
                replacer.set_color( expellee.is_red() );
            }
            typename details::rbtree_node<T>::child_t * new_child;
            auto ecp = details::get_child_position( expellee_parent, expellee );
            if ( ecp == details::left_child ) {
                expellee_parent.get_pointer()->m_left = replacer;
                new_child = &expellee_parent.get_pointer()->m_left;
            }
            else {
                expellee_parent.get_pointer()->m_right = replacer;
                new_child = &expellee_parent.get_pointer()->m_right;
            }
            if ( m_root == expellee ) {
                m_root = *new_child;
            }
            return new_child;
        }

        // After rotating, the child and the parent change their position
        void rotate(
            typename details::rbtree_node<T>::child_t * grandparent,
            typename details::rbtree_node<T>::child_t parent,
            typename details::rbtree_node<T>::child_t child,
            typename details::rbtree_node<T>::child_t ** new_parent = NULL,
            typename details::rbtree_node<T>::child_t ** new_child = NULL
        )
        {
            assert( grandparent == NULL || details::has_filiation( *grandparent, parent ) );
            assert( details::has_filiation( parent, child ) );
            details::child_position ccp = details::get_child_position( parent, child );
            details::child_position pcp = details::left_child;
            if ( grandparent != NULL ) {
                pcp = details::get_child_position( *grandparent, parent );
            }
            if ( ccp == details::left_child ) {
                parent.get_pointer()->m_left = child.get_pointer()->m_right;
                child.get_pointer()->m_right = parent;
                if ( new_child != NULL ) {
                    *new_child = &child.get_pointer()->m_right;
                }
            } else {
                parent.get_pointer()->m_right = child.get_pointer()->m_left;
                child.get_pointer()->m_left = parent;
                if ( new_child != NULL ) {
                    *new_child = &child.get_pointer()->m_left;
                }
            }
            if ( grandparent != NULL ) {
                if ( pcp == details::left_child ) {
                    grandparent->get_pointer()->m_left = child;
                    if ( new_parent != NULL ) {
                        *new_parent = &grandparent->get_pointer()->m_left;
                    }
                } else {
                    grandparent->get_pointer()->m_right = child;
                    if ( new_parent != NULL ) {
                        *new_parent = &grandparent->get_pointer()->m_right;
                    }
                }
            } else {
                m_root = child;
                if ( new_parent != NULL ) {
                    *new_parent = &m_root;
                }
            }
        }

        void erasing_rebalance(
            typename details::rbtree_node<T>::child_t * replacement,
            details::child_position rcp,
            std::stack<typename details::rbtree_node<T>::child_t *> & ancestors
        )
        {
            assert( !ancestors.empty() );
            for (
                typename details::rbtree_node<T>::child_t * parent = details::pop_without_doubt( ancestors );
                parent != NULL;
                parent = details::pop( ancestors )
            ) {
                assert( details::has_filiation( *parent, *replacement ) );
                typename details::rbtree_node<T>::child_t * grandparent = NULL;
                if ( !ancestors.empty() ) {
                    grandparent = ancestors.top();
                    assert(details::has_filiation(*grandparent, *parent));
                    if ( details::get_child_position(*grandparent, *parent) == details::left_child ) {
                        parent = &grandparent->get_pointer()->m_left;
                    }
                    else {
                        parent = &grandparent->get_pointer()->m_right;
                    }
                }
                else {
                    parent = &m_root;
                }

                typename details::rbtree_node<T>::child_t * sibling = details::get_other_child( *parent, rcp );

                if ( sibling->is_non_null() && sibling->is_black() && sibling->get_pointer()->m_left.is_black() && sibling->get_pointer()->m_right.is_black() ) {
                    sibling->set_red();
                    if ( parent->is_black() ) {
                        replacement = parent;
                        if ( !ancestors.empty() ) {
                            rcp = details::get_child_position( *ancestors.top(), *replacement );
                        }
                    }
                    else {
                        parent->set_black();
                        break;
                    }
                }
                else {
                    if ( !sibling->is_black() ) {
                        // we cannot use the logical listed in CLRS, because our implementation is based on 2-3-4-tree
                        assert( details::has_filiation( *parent, *replacement ) );
                        assert( parent->is_black() );
                        if ( !ancestors.empty() ) {
                            grandparent = ancestors.top();
                        }
                        sibling->set_black();
                        if ( rcp == details::left_child ) {
                            if ( sibling->get_pointer()->m_left.is_non_null() ) {
                                sibling->get_pointer()->m_left.set_red();
                            }
                        }
                        else {
                            if ( sibling->get_pointer()->m_right.is_non_null() ) {
                                sibling->get_pointer()->m_right.set_red();
                            }
                        }
                        rotate( grandparent, *parent, *sibling, &grandparent, &parent );
                        if ( rcp == details::left_child ) {
                            sibling = &parent->get_pointer()->m_right;
                        } else {
                            sibling = &parent->get_pointer()->m_left;
                        }
                        assert( details::has_filiation( *grandparent, *parent ) );
                        assert( details::has_filiation( *parent, *replacement ) );
                        assert( details::has_filiation( *parent, *sibling ) );
                        if ( sibling->is_non_null() ) {
                            bool left_is_red = !sibling->get_pointer()->m_left.is_black(), right_is_red = !sibling->get_pointer()->m_right.is_black();
                            if ( left_is_red || right_is_red ) {
                                typename details::rbtree_node<T>::child_t * child = &sibling->get_pointer()->m_left;
                                if ( right_is_red ) {
                                    child = &sibling->get_pointer()->m_right;
                                }

                                std::stack<typename details::rbtree_node<T>::child_t *> new_ancestors;
                                new_ancestors.push( grandparent );
                                new_ancestors.push( parent );
                                parent = sibling;
                                details::child_position ccp;
                                rebalance_nodes_in_the_different_branch(new_ancestors, &parent, &child, &ccp);
                                rebalance_nodes_in_the_same_branch(new_ancestors, parent, &child, ccp);
                            }
                        }
                    }
                    else {
                        if ( rcp == details::left_child ) {
                            if ( !sibling->get_pointer()->m_left.is_black() ) {
                                sibling->set_red();
                                sibling->get_pointer()->m_left.set_black();
                                rotate( parent, *sibling, sibling->get_pointer()->m_left );
                                sibling = &parent->get_pointer()->m_right;
                            }
                            sibling->set_color( parent->is_red() );
                            parent->set_black();
                            sibling->get_pointer()->m_right.set_black();
                            rotate( grandparent, *parent, *sibling );
                        } else {
                            if ( !sibling->get_pointer()->m_right.is_black() ) {
                                sibling->set_red();
                                sibling->get_pointer()->m_right.set_black();
                                rotate( parent, *sibling, sibling->get_pointer()->m_right );
                                sibling = &parent->get_pointer()->m_left;
                            }
                            sibling->set_color( parent->is_red() );
                            parent->set_black();
                            sibling->get_pointer()->m_left.set_black();
                            rotate( grandparent, *parent, *sibling );
                        }
                    }
                    break;
                }
            }
        }

        struct height_record
        {
            size_t height;
            size_t width;
        };

        static void calculate_height(
            typename details::rbtree_node<T>::child_t const node,
            std::unordered_map<typename details::rbtree_node<T>::child_t const, height_record, typename details::rbtree_node<T>::hash> & cache
        )
        {
            if ( cache.find( node ) == cache.end() && node.is_non_null() ) {
                calculate_height( node.get_pointer()->m_left, cache );
                height_record & left = cache[ node.get_pointer()->m_left ];
                calculate_height( node.get_pointer()->m_right, cache );
                height_record & right = cache[ node.get_pointer()->m_right ];
                size_t width = left.height + right.height;
                if ( width < left.width ) {
                    width = left.width;
                }
                if ( width < right.width ) {
                    width = right.width;
                }
                height_record self = { ( left.height < right.height ? right.height : left.height ) + 1, width };
                cache[ node ] = std::move( self );
            }
        }
    public:
        rbtree() {}
        rbtree( rbtree<T> const & );
        rbtree<T> & operator=( rbtree<T> const & );

        void insert( typename boost::call_traits<T>::param_type t )
        {
            assert( details::is_rb_tree<T>( m_root ) );
            std::stack<typename details::rbtree_node<T>::child_t *> stack;
            typename details::rbtree_node<T>::child_t * child = NULL;
            details::search_result sr = details::find<T>( &m_root, t, &stack, &child );
            if ( ( sr & ( details::empty_tree | details::should_insert_as_left | details::should_insert_as_right ) ) != 0 ) {
                details::rbtree_node<T> * new_node = new details::rbtree_node<T>( t );
                switch ( sr ) {
                case details::empty_tree:
                    assert( m_root.is_null() );
                    m_root.pointer = new_node;
                    return;
                case details::should_insert_as_left:
                    stack.top()->get_pointer()->m_left.pointer = new_node;
                    child = &stack.top()->get_pointer()->m_left;
                    break;
                case details::should_insert_as_right:
                    stack.top()->get_pointer()->m_right.pointer = new_node;
                    child = &stack.top()->get_pointer()->m_right;
                    break;
                default:
                    assert( false && "bug" );
                }
                child->set_red();
                insertion_rebalance( child, stack );
                m_root.set_black();
            }
            assert( details::is_rb_tree<T>( m_root ) );
        }

        size_t width() const
        {
            std::unordered_map<typename details::rbtree_node<T>::child_t const, height_record, typename details::rbtree_node<T>::hash> cache;
            height_record hr = { 0, 0 };
            cache[ typename details::rbtree_node<T>::child_t() ] = std::move( hr );
            calculate_height( m_root, cache );
            return cache[ m_root ].width;
        }

        void erase( typename boost::call_traits<T>::param_type t )
        {
            assert( details::is_rb_tree<T>( m_root ) );
            bool need_to_reblance = false;
            std::stack<typename details::rbtree_node<T>::child_t *> ancestors;
            details::rbtree_node<T> dummy_node;
            details::child_position rcp;
            typename details::rbtree_node<T>::child_t * expellee = NULL, dummy;
            auto result = details::find<T>( &m_root, t, &ancestors, &expellee );
            if ( result == details::found_node ) {
                typename details::rbtree_node<T>::child_t expellee_ref;
                need_to_reblance = true;
                typename details::rbtree_node<T>::child_t * expellee_parent = NULL;
                if ( !ancestors.empty() ) {
                    expellee_parent = ancestors.top();
                }
                if ( expellee_parent == NULL ) {
                    assert( m_root == *expellee );
                    dummy_node.m_left = m_root;
                    dummy.pointer = &dummy_node;
                    expellee_parent = &dummy;
                }
                expellee_ref = *expellee;
                assert( expellee != NULL && expellee->is_non_null() );
                typename details::rbtree_node<T>::child_t * replacement;
                if ( expellee->get_pointer()->m_right.is_non_null() ) {
                    std::vector<typename details::rbtree_node<T>::child_t *> new_ancestors;
                    replacement = details::get_minimum_child( expellee, new_ancestors );
                    assert( replacement != NULL && replacement->is_non_null() );
                    assert( !new_ancestors.empty() );
                    assert( details::height( *replacement ) <= 2 );
                    if ( replacement->get_pointer()->m_right.is_non_null() || replacement->is_red() ) {
                        //the replacement is a 3-node, we only need to change the 3-node to a 2-node
                        if ( replacement->get_pointer()->m_right.is_non_null() ) {
                            assert( replacement->get_pointer()->m_right.is_red() && replacement->is_black() );
                            replacement->get_pointer()->m_right.set_black();
                        }
                        need_to_reblance = false;
                    }
                    auto replacement_ref = *replacement;
                    auto expellee_ref = *expellee;
                    rcp = details::get_child_position( *new_ancestors.back(), replacement_ref );
                    replacement = transplant( *new_ancestors.back(), replacement_ref, replacement_ref.get_pointer()->m_right );
                    expellee = transplant( *expellee_parent, expellee_ref, replacement_ref );
                    if ( need_to_reblance ) {
                        ancestors.push( expellee );
                        std::for_each(
                            new_ancestors.begin() + 1, new_ancestors.end(),
                            [&ancestors]( typename details::rbtree_node<T>::child_t * node ) { ancestors.push( node ); }
                        );
                    }
                }
                else {
                    assert( details::height( *expellee ) <= 2 );
                    need_to_reblance = *expellee != m_root;
                    if ( expellee->get_pointer()->m_left.is_non_null() ) {
                        //it is a 3-node
                        assert( expellee->get_pointer()->m_left.is_red() );
                        need_to_reblance = false;
                    }
                    else if ( expellee->is_red() ) {
                        //it is a 3-node
                        assert( expellee->get_pointer()->m_left.is_null() && expellee->get_pointer()->m_right.is_null() );
                        need_to_reblance = false;
                    }
                    rcp = details::get_child_position( *expellee_parent, *expellee );
                    replacement = transplant( *expellee_parent, *expellee, expellee->get_pointer()->m_left );
                }
                if ( need_to_reblance ) {
                    assert( replacement->is_null() );
                    erasing_rebalance( replacement, rcp, ancestors );
                }
                delete expellee_ref.get_pointer();
                assert( details::is_rb_tree<T>( m_root ) );
            }
        }

        template <typename Visitor>
        void levelorder_visit( Visitor visitor ) const
        {
            details::levelorder_visit( m_root, visitor );
        }

        bool is_valid( ) const { return details::is_rb_tree<T>( m_root ); }
    };
}

#endif //GYM_RED_BLACK_TREE_H_6D4EBDB0_5B18_4FC1_A34A_CBBF36FE95E4


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值