Algo Algo   C++   C#   Demo   JS   Py   SQL   Stat   TA

Structure : Red Black Tree

A red–black tree is a self-balancing binary search tree. Balance is preserved by painting each node of the tree with one of two colors in a way that satisfies certain properties. O(log n) search / insert / delete

// -----------------------------------------------------------------------------
// Red Black Tree                                                             C#
// -----------------------------------------------------------------------------
// RedBlackTree(IComparer<T> comparer)
// int ElementCount
// RedBlackTree<T> Clone()
// bool Find(T key, bool findFirst, bool replace, out T item)
// int FindIndex(T key, bool findFirst)
// T GetItemByIndex(int index)
// bool Insert(T item, DuplicatePolicy dupPolicy, out T previous)
// bool Delete(T key, bool deleteFirst, out T item)
// IEnumerator<T> GetEnumerator()
// Func<T, int> BoundedRange(bool useFirst, T first, bool useLast, T last)
// Func<T, int> DoubleBoundedRange(T first, bool firstInclusive,
//                                 T last, bool lastInclusive)
// Func<T, int> LowerBoundedRange(T first, bool inclusive)
// Func<T, int> UpperBoundedRange(T last, bool inclusive)
// Func<T, int> EqualRange(T equalTo)
// int EntireRange(T item)
// IEnumerable<T> EnumerateRange(Func<T, int> range)
// IEnumerable<T> EnumerateRangeReversed(Func<T, int> range)
// bool DeleteItemFromRange(Func<T, int> range, bool deleteFirst, out T item)
// int DeleteRange(Func<T, int> range)
// int CountRange(Func<T, int> range)
// int FirstItemInRange(Func<T, int> range, out T item)
// int LastItemInRange(Func<T, int> range, out T item)
// -----------------------------------------------------------------------------
enum DuplicatePolicy
{
    InsertFirst,
    InsertLast,
    ReplaceFirst,
    ReplaceLast,
    DoNothing
};

class RedBlackTree<T> : IEnumerable<T>
{
    private readonly IComparer<T> comparer;
    private Node root;
    private int count;
    private int changeStamp;
    private Node[] stack;

    private Node[] GetNodeStack()
    {
        int maxDepth;
        if (count < 0x400)
            maxDepth = 21;
        else if (count < 0x10000)
            maxDepth = 41;
        else
            maxDepth = 65;
        if (stack == null || stack.Length < maxDepth)
            stack = new Node[maxDepth];
        return stack;
    }

    private class Node
    {
        public Node left, right;
        public T item;
        private const uint REDMASK = 0x80000000;
        private uint count;

        public bool IsRed
        {
            get { return (count & REDMASK) != 0; }
            set
            {
                if (value)
                    count |= REDMASK;
                else
                    count &= ~REDMASK;
            }
        }

        public int Count
        {
            get { return (int)(count & ~REDMASK); }
            set { count = (count & REDMASK) | (uint)value; }
        }

        public void IncrementCount()
        {
            ++count;
        }

        public void DecrementCount()
        {
            --count;
        }

        public Node Clone()
        {
            Node newNode = new Node();
            newNode.item = item;
            newNode.count = count;

            if (left != null)
                newNode.left = left.Clone();
            if (right != null)
                newNode.right = right.Clone();

            return newNode;
        }
    }

    internal void StopEnumerations()
    {
        ++changeStamp;
    }

    private void CheckEnumerationStamp(int startStamp)
    {
        if (startStamp != changeStamp)
        {
            throw new InvalidOperationException("Collection was modified");
        }
    }

    public RedBlackTree(IComparer<T> comparer)
    {
        this.comparer = comparer;
        this.count = 0;
        this.root = null;
    }

    public int ElementCount
    {
        get { return count; }
    }

    public RedBlackTree<T> Clone()
    {
        RedBlackTree<T> newTree = new RedBlackTree<T>(comparer);
        newTree.count = this.count;
        if (this.root != null)
            newTree.root = this.root.Clone();
        return newTree;
    }

    public bool Find(T key, bool findFirst, bool replace, out T item)
    {
        Node current = root;
        Node found = null;

        while (current != null)
        {
            int compare = comparer.Compare(key, current.item);

            if (compare < 0)
                current = current.left;
            else if (compare > 0)
                current = current.right;
            else
            {
                found = current;
                if (findFirst)
                    current = current.left;
                else
                    current = current.right;
            }
        }

        if (found != null)
        {
            item = found.item;
            if (replace)
                found.item = key;
            return true;
        }
        else
        {
            item = default(T);
            return false;
        }
    }

    public int FindIndex(T key, bool findFirst)
    {
        T dummy;
        if (findFirst)
            return FirstItemInRange(EqualRange(key), out dummy);
        else
            return LastItemInRange(EqualRange(key), out dummy);
    }

    public T GetItemByIndex(int index)
    {
        if (index < 0 || index >= count)
            throw new ArgumentOutOfRangeException("index");

        Node current = root;
        for (; ; )
        {
            int leftCount;

            if (current.left != null)
                leftCount = current.left.Count;
            else
                leftCount = 0;

            if (leftCount > index)
                current = current.left;
            else if (leftCount == index)
                return current.item;
            else
            {
                index -= leftCount + 1;
                current = current.right;
            }
        }
    }

    public bool Insert(T item, DuplicatePolicy dupPolicy, out T previous)
    {
        Node node = root;
        Node parent = null, gparent = null, ggparent = null;
        bool wentLeft = false, wentRight = false;
        bool rotated;
        Node duplicateFound = null;

        StopEnumerations();

        bool needStack = !((dupPolicy == DuplicatePolicy.InsertFirst) ||
                           (dupPolicy == DuplicatePolicy.InsertLast));
        Node[] nodeStack = null;
        int nodeStackPtr = 0;
        if (needStack)
            nodeStack = GetNodeStack();

        while (node != null)
        {
            if (node.left != null && node.left.IsRed &&
                node.right != null && node.right.IsRed)
            {
                node = InsertSplit(ggparent, gparent, parent, node,
                                   out rotated);
                if (needStack && rotated)
                {
                    nodeStackPtr -= 2;
                    if (nodeStackPtr < 0)
                        nodeStackPtr = 0;
                }
            }
            ggparent = gparent; gparent = parent; parent = node;
            int compare = comparer.Compare(item, node.item);
            if (compare == 0)
            {
                if (dupPolicy == DuplicatePolicy.DoNothing)
                {
                    previous = node.item;
                    for (int i = 0; i < nodeStackPtr; ++i)
                        nodeStack[i].DecrementCount();
                    return false;
                }
                else if (dupPolicy == DuplicatePolicy.InsertFirst ||
                         dupPolicy == DuplicatePolicy.ReplaceFirst)
                {
                    duplicateFound = node;
                    compare = -1;
                }
                else
                {
                    duplicateFound = node;
                    compare = 1;
                }
            }

            node.IncrementCount();
            if (needStack)
                nodeStack[nodeStackPtr++] = node;

            if (compare < 0)
            {
                node = node.left;
                wentLeft = true; wentRight = false;
            }
            else
            {
                node = node.right;
                wentRight = true; wentLeft = false;
            }
        }

        if (duplicateFound != null)
        {
            previous = duplicateFound.item;
            if (dupPolicy == DuplicatePolicy.ReplaceFirst ||
                dupPolicy == DuplicatePolicy.ReplaceLast)
            {
                duplicateFound.item = item;
                for (int i = 0; i < nodeStackPtr; ++i)
                    nodeStack[i].DecrementCount();

                return false;
            }
        }
        else
        {
            previous = default(T);
        }

        node = new Node();
        node.item = item;
        node.Count = 1;

        if (wentLeft)
            parent.left = node;
        else if (wentRight)
            parent.right = node;
        else
            root = node;

        InsertSplit(ggparent, gparent, parent, node, out rotated);

        count += 1;

        return (duplicateFound == null);
    }

    private Node InsertSplit(
        Node ggparent, Node gparent, Node parent, Node node,
        out bool rotated)
    {
        if (node != root)
            node.IsRed = true;
        if (node.left != null)
            node.left.IsRed = false;
        if (node.right != null)
            node.right.IsRed = false;

        if (parent != null && parent.IsRed)
        {
            if ((gparent.left == parent) != (parent.left == node))
            {
                Rotate(gparent, parent, node);
                parent = node;
            }

            gparent.IsRed = true;

            Rotate(ggparent, gparent, parent);

            parent.IsRed = false;
            rotated = true;
            return parent;
        }
        else
        {
            rotated = false;
            return node;
        }
    }

    private void Rotate(Node node, Node child, Node gchild)
    {
        if (gchild == child.left)
        {
            child.left = gchild.right;
            gchild.right = child;
        }
        else
        {
            child.right = gchild.left;
            gchild.left = child;
        }

        child.Count = (child.left != null ? child.left.Count : 0) +
                      (child.right != null ? child.right.Count : 0) + 1;
        gchild.Count = (gchild.left != null ? gchild.left.Count : 0) +
                       (gchild.right != null ? gchild.right.Count : 0) + 1;

        if (node == null)
            root = gchild;
        else if (child == node.left)
            node.left = gchild;
        else
            node.right = gchild;
    }

    public bool Delete(T key, bool deleteFirst, out T item)
    {
        return DeleteItemFromRange(EqualRange(key), deleteFirst, out item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return EnumerateRange(EntireRange).GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public Func<T, int> BoundedRange(bool useFirst, T first,
                                     bool useLast, T last)
    {
        return delegate (T item) {
            if (useFirst && comparer.Compare(first, item) > 0)
                return -1;
            else if (useLast && comparer.Compare(last, item) <= 0)
                return 1;
            else
                return 0;
        };
    }

    public Func<T, int> DoubleBoundedRange(T first, bool firstInclusive,
                                           T last, bool lastInclusive)
    {
        return delegate (T item) {
            if (firstInclusive)
            {
                if (comparer.Compare(first, item) > 0) return -1;
            }
            else
            {
                if (comparer.Compare(first, item) >= 0) return -1;
            }

            if (lastInclusive)
            {
                if (comparer.Compare(last, item) < 0) return 1;
            }
            else
            {
                if (comparer.Compare(last, item) <= 0) return 1;
            }

            return 0;
        };
    }

    public Func<T, int> LowerBoundedRange(T first, bool inclusive)
    {
        return delegate (T item) {
            if (inclusive)
            {
                if (comparer.Compare(first, item) > 0)
                    return -1;
                else
                    return 0;
            }
            else
            {
                if (comparer.Compare(first, item) >= 0)
                    return -1;
                else
                    return 0;
            }
        };
    }

    public Func<T, int> UpperBoundedRange(T last, bool inclusive)
    {
        return delegate (T item) {
            if (inclusive)
            {
                if (comparer.Compare(last, item) < 0)
                    return 1;
                else
                    return 0;
            }
            else
            {
                if (comparer.Compare(last, item) <= 0)
                    return 1;
                else
                    return 0;
            }
        };
    }

    public Func<T, int> EqualRange(T equalTo)
    {
        return delegate (T item) {
            return comparer.Compare(item, equalTo);
        };
    }

    public int EntireRange(T item)
    {
        return 0;
    }

    public IEnumerable<T> EnumerateRange(Func<T, int> range)
    {
        return EnumerateRangeInOrder(range, root);
    }

    private IEnumerable<T> EnumerateRangeInOrder(Func<T, int> range, Node node)
    {
        int startStamp = changeStamp;

        if (node != null)
        {
            int compare = range(node.item);

            if (compare >= 0)
            {
                foreach (T item in EnumerateRangeInOrder(range, node.left))
                {
                    yield return item;
                    CheckEnumerationStamp(startStamp);
                }
            }

            if (compare == 0)
            {
                yield return node.item;
                CheckEnumerationStamp(startStamp);
            }

            if (compare <= 0)
            {
                foreach (T item in EnumerateRangeInOrder(range, node.right))
                {
                    yield return item;
                    CheckEnumerationStamp(startStamp);
                }
            }
        }
    }

    public IEnumerable<T> EnumerateRangeReversed(Func<T, int> range)
    {
        return EnumerateRangeInReversedOrder(range, root);
    }

    private IEnumerable<T> EnumerateRangeInReversedOrder(Func<T, int> range,
                                                         Node node)
    {
        int startStamp = changeStamp;

        if (node != null)
        {
            int compare = range(node.item);

            if (compare <= 0)
            {
                foreach (T item in EnumerateRangeInReversedOrder(range, node.right))
                {
                    yield return item;
                    CheckEnumerationStamp(startStamp);
                }
            }

            if (compare == 0)
            {
                yield return node.item;
                CheckEnumerationStamp(startStamp);
            }

            if (compare >= 0)
            {
                foreach (T item in EnumerateRangeInReversedOrder(range, node.left))
                {
                    yield return item;
                    CheckEnumerationStamp(startStamp);
                }
            }
        }
    }

    public bool DeleteItemFromRange(Func<T, int> range, bool deleteFirst, out T item)
    {
        Node node;
        Node parent;
        Node gparent;
        Node sib;
        Node keyNode;

        StopEnumerations();

        if (root == null)
        {
            item = default(T);
            return false;
        }

        Node[] nodeStack = GetNodeStack();
        int nodeStackPtr = 0;

        node = root;
        sib = parent = gparent = null;
        keyNode = null;

        for (; ; )
        {
            if ((node.left == null || !node.left.IsRed) &&
                (node.right == null || !node.right.IsRed))
            {
                if (parent == null)
                    node.IsRed = true;
                else if ((sib.left == null || !sib.left.IsRed) &&
                         (sib.right == null || !sib.right.IsRed))
                {
                    node.IsRed = true;
                    sib.IsRed = true;
                    parent.IsRed = false;
                }
                else
                {
                    if (parent.left == node &&
                        (sib.right == null || !sib.right.IsRed))
                    {
                        Node tleft = sib.left;
                        Rotate(parent, sib, tleft);
                        sib = tleft;
                    }
                    else if (parent.right == node &&
                             (sib.left == null || !sib.left.IsRed))
                    {
                        Node tright = sib.right;
                        Rotate(parent, sib, tright);
                        sib = tright;
                    }

                    Rotate(gparent, parent, sib);
                    node.IsRed = true;
                    sib.IsRed = true;
                    sib.left.IsRed = false;
                    sib.right.IsRed = false;

                    sib.DecrementCount();
                    nodeStack[nodeStackPtr - 1] = sib;
                    parent.DecrementCount();
                    nodeStack[nodeStackPtr++] = parent;
                }
            }

            do
            {
                Node nextNode, nextSib;

                node.DecrementCount();
                nodeStack[nodeStackPtr++] = node;
                int compare = range(node.item);

                if (compare == 0)
                {
                    keyNode = node;
                    if (deleteFirst)
                    {
                        nextNode = node.left; nextSib = node.right;
                    }
                    else
                    {
                        nextNode = node.right; nextSib = node.left;
                    }
                }
                else if (compare > 0)
                {
                    nextNode = node.left; nextSib = node.right;
                }
                else
                {
                    nextNode = node.right; nextSib = node.left;
                }

                if (nextNode == null)
                    goto FINISHED;

                gparent = parent;
                parent = node;
                node = nextNode;
                sib = nextSib;
            } while (!parent.IsRed && node.IsRed);

            if (!parent.IsRed)
            {
                Rotate(gparent, parent, sib);

                sib.DecrementCount();
                nodeStack[nodeStackPtr - 1] = sib;
                parent.DecrementCount();
                nodeStack[nodeStackPtr++] = parent;

                sib.IsRed = false;
                parent.IsRed = true;
                gparent = sib;
                sib = (parent.left == node) ? parent.right : parent.left;
            }
        }

        FINISHED:
        if (keyNode == null)
        {
            for (int i = 0; i < nodeStackPtr; ++i)
                nodeStack[i].IncrementCount();

            if (root != null)
                root.IsRed = false;

            item = default(T);
            return false;
        }

        item = keyNode.item;

        if (keyNode != node)
        {
            keyNode.item = node.item;
        }

        Node replacement;
        if (node.left != null)
        {
            replacement = node.left;
            replacement.IsRed = false;
        }
        else if (node.right != null)
        {
            replacement = node.right;
            replacement.IsRed = false;
        }
        else
            replacement = null;

        if (parent == null)
            root = replacement;
        else if (parent.left == node)
            parent.left = replacement;
        else
            parent.right = replacement;

        if (root != null)
            root.IsRed = false;
        count -= 1;
        return true;
    }

    public int DeleteRange(Func<T, int> range)
    {
        bool deleted;
        int counter = 0;
        T dummy;

        do
        {
            deleted = DeleteItemFromRange(range, true, out dummy);
            if (deleted)
                ++counter;
        } while (deleted);

        return counter;
    }

    public int CountRange(Func<T, int> range)
    {
        return CountRangeUnderNode(range, root, false, false);
    }

    private int CountRangeUnderNode(Func<T, int> range, Node node,
                                    bool belowRangeTop, bool aboveRangeBottom)
    {
        if (node != null)
        {
            if (belowRangeTop && aboveRangeBottom)
                return node.Count;

            int compare = range(node.item);
            int counter;

            if (compare == 0)
            {
                counter = 1;
                counter += CountRangeUnderNode(range, node.left,
                                               true, aboveRangeBottom);
                counter += CountRangeUnderNode(range, node.right,
                                               belowRangeTop, true);
            }
            else if (compare < 0)
                counter = CountRangeUnderNode(range, node.right,
                                              belowRangeTop, aboveRangeBottom);
            else
                counter = CountRangeUnderNode(range, node.left,
                                              belowRangeTop, aboveRangeBottom);

            return counter;
        }
        else
        {
            return 0;
        }
    }

    public int FirstItemInRange(Func<T, int> range, out T item)
    {
        Node node = root, found = null;
        int curCount = 0, foundIndex = -1;

        while (node != null)
        {
            int compare = range(node.item);

            if (compare == 0)
            {
                found = node;
                if (node.left != null)
                    foundIndex = curCount + node.left.Count;
                else
                    foundIndex = curCount;
            }

            if (compare >= 0)
                node = node.left;
            else
            {
                if (node.left != null)
                    curCount += node.left.Count + 1;
                else
                    curCount += 1;
                node = node.right;
            }
        }

        if (found != null)
        {
            item = found.item;
            return foundIndex;
        }
        else
        {
            item = default(T);
            return -1;
        }
    }

    public int LastItemInRange(Func<T, int> range, out T item)
    {
        Node node = root, found = null;
        int curCount = 0, foundIndex = -1;

        while (node != null)
        {
            int compare = range(node.item);

            if (compare == 0)
            {
                found = node;
                if (node.left != null)
                    foundIndex = curCount + node.left.Count;
                else
                    foundIndex = curCount;
            }

            if (compare <= 0)
            {
                if (node.left != null)
                    curCount += node.left.Count + 1;
                else
                    curCount += 1;
                node = node.right;
            }
            else
                node = node.left;
        }

        if (found != null)
        {
            item = found.item;
            return foundIndex;
        }
        else
        {
            item = default(T);
            return foundIndex;
        }
    }
}
// -----------------------------------------------------------------------------
Algo Algo   C++   C#   Demo   JS   Py   SQL   Stat   TA