private RbNode InsertionBalance(RbNode current, RbNode parent, RbNode grandParent, RbNode greatGrandParent)
            {
                var parentIsOnRight  = (grandParent.Right == parent);
                var currentIsOnRight = (parent.Right == current);

                RbNode newChildOfGreatGrandParent;

                if (parentIsOnRight == currentIsOnRight)
                {
                    // same orientation, single rotation
                    newChildOfGreatGrandParent = currentIsOnRight ? RotateLeft(grandParent) : RotateRight(grandParent);
                }
                else
                {
                    // different orientaton, double rotation
                    newChildOfGreatGrandParent = (currentIsOnRight ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent));

                    // current node now becomes the child of greatgrandparent
                    parent = greatGrandParent;
                }
                // grand parent will become a child of either parent of current.
                grandParent.IsRed = true;
                newChildOfGreatGrandParent.IsRed = false;

                ReplaceChildOrRoot(greatGrandParent, grandParent, newChildOfGreatGrandParent);

                return(parent);
            }
            private RbNode RotateLeft(RbNode node)
            {
                var x = node.Right;

                node.Right = x.Left;
                x.Left     = node;
                return(x);
            }
            private RbNode RotateRightLeft(RbNode node)
            {
                var child      = node.Right;
                var grandChild = child.Left;

                node.Right      = grandChild.Left;
                grandChild.Left = node;

                child.Left       = grandChild.Right;
                grandChild.Right = child;

                return(grandChild);
            }
 private void ReplaceChildOrRoot(RbNode parent, RbNode child, RbNode newChild)
 {
     if (parent != null)
     {
         if (parent.Left == child)
         {
             parent.Left = newChild;
         }
         else
         {
             parent.Right = newChild;
         }
     }
     else
     {
         _root = newChild;
     }
 }
            private IEnumerable <RbNode> InOrderTravers(RbNode node)
            {
                /*
                 * iterativeInorder(node)
                 * parentStack = empty stack
                 * while (not parentStack.isEmpty() or node ≠ null)
                 *  if (node ≠ null)
                 *    parentStack.push(node)
                 *    node = node.left
                 *  else
                 *    node = parentStack.pop()
                 *    visit(node)
                 *    node = node.right
                 */

                if (node == null)
                {
                    yield break;
                }

                var capacity    = 2 * (int)Math.Log(_count + 1, 2);
                var parentStack = new Stack <RbNode>(capacity);

                while (parentStack.Count > 0 || node != null)
                {
                    if (node != null)
                    {
                        parentStack.Push(node);
                        node = node.Left;
                    }
                    else
                    {
                        node = parentStack.Pop();
                        yield return(node);

                        node = node.Right;
                    }
                }
            }
            public void Add(int index)
            {
                if (_root == null)
                {
                    _root = new RbNode(index, false);
                    return;
                }

                var current          = _root;
                var parent           = (RbNode)null;
                var grandParent      = (RbNode)null;
                var greatGrandParent = (RbNode)null;

                var order = 0;

                while (current != null)
                {
                    order = CompareItems(index, current.Index);
                    if (order == 0)
                    {
                        _root.IsRed = false;
                        _count++;

                        return;
                    }

                    if (Is4Node(current))
                    {
                        Split4Node(current);

                        if (IsRed(parent))
                        {
                            parent = InsertionBalance(current, parent, grandParent, greatGrandParent);
                        }
                    }

                    greatGrandParent = grandParent;
                    grandParent      = parent;

                    parent  = current;
                    current = (order < 0) ? current.Left : current.Right;
                }

                var node = new RbNode(index);

                if (order > 0)
                {
                    parent.Right = node;
                }
                else
                {
                    parent.Left = node;
                }

                if (parent.IsRed)
                {
                    parent = InsertionBalance(node, parent, grandParent, greatGrandParent);
                }

                _root.IsRed = false;
                _count++;
            }
 private void Split4Node(RbNode node)
 {
     node.IsRed       = true;
     node.Left.IsRed  = false;
     node.Right.IsRed = false;
 }
 private bool Is4Node(RbNode node)
 {
     return(IsRed(node.Left) && IsRed(node.Right));
 }
 private bool IsRed(RbNode node)
 {
     return(node != null && node.IsRed);
 }