redblacktree_splice.hpp

Back to Red-black tree

pastel/sys/redblacktree/

#ifndef PASTELSYS_REDBLACKTREE_SPLICE_HPP
#define PASTELSYS_REDBLACKTREE_SPLICE_HPP

#include "pastel/sys/redblacktree.h"

namespace Pastel
{

    template <typename Settings, template <typename> class Customization>
    auto RedBlackTree<Settings, Customization>::splice(
        RedBlackTree& that,
        const ConstIterator& thatFrom)
    -> Insert_Return
    {
        Iterator element = cast(thatFrom);
        Node* node = element.base();
        if (element.isSentinel())
        {
            ENSURE(element == that.end());
            return insertReturnType(end(), false);
        }

        if (this == &that && !Settings::MultipleKeys)
        {
            // The splicing is done inside this tree.
            // Since in addition every key is unique, 
            // this has no effect.
            return insertReturnType(element, false);
        }

        // Notify the customization of 'that' tree.
        that.onSpliceFrom(element);

        // Detach the node from 'that' tree.
        that.detach(node);

        auto equalAndUpper = findEqualAndUpper(element.key());
        bool keyExists = (equalAndUpper.equal != cend());
        if (!Settings::MultipleKeys && keyExists)
        {
            // The tree already contains an
            // equivalent element. 

            // Compute the lower-bound for the element.
            ConstIterator lower =
                lowerBound(element.key(), equalAndUpper, All_DownFilter());

            // Remove the detached element.
            that.deallocateNode((Key_Node*)node);

            // Return the existing element.
            return insertReturnType(cast(lower), false);
        }

        // Find the place where to insert the element.
        auto parentAndRight = findInsert(element.key(), equalAndUpper);
        Iterator parent = cast(parentAndRight.parent);
        bool right = parentAndRight.right;

        // Attach the new node into this tree.
        Node* updateNode = attach(node, parent.base(), right);

        // Update propagation data upwards.
        updateToRoot(updateNode);

        // Notify the customization of this tree.
        this->onSplice(element);

        // Return an iterator to the new element.
        return insertReturnType(element, true);
    }

}

#endif