コード例 #1
0
        /// <summary>
        /// Perform rebalancing on the red-black tree for a deletion.  O(lg n).
        /// If we broke the tree by moving a black node, we need to reorder
        /// and/or recolor part of it.  This is not pretty, and is basically
        /// derived from the algorithm in Cormen/Leiserson/Rivest, just like
        /// every other red-black tree implementation.  We have, however, gone
        /// to the necessary work to drop out the required sentinel value in
        /// their version, so this is a little more flexible.
        /// </summary>
        /// <param name="child">The child that was removed.</param>
        /// <param name="parent">The parent it was removed from.</param>
        /// <param name="rightSide">Which side of the parent it was removed from.</param>
        private void DetachFixup(WeightedRedBlackTreeNode <K, V> child, WeightedRedBlackTreeNode <K, V> parent, bool rightSide)
        {
            while (child != Root && child.IsBlack())
            {
                if (!rightSide)
                {
                    WeightedRedBlackTreeNode <K, V> other = parent.Right;
                    if (other.IsRed())
                    {
                        other.MakeNodeBlack();
                        parent.MakeNodeRed();
                        RotateLeft(parent);
                        other = parent.Right;
                    }
                    if (other == null ||
                        (other.Left.IsBlack() &&
                         other.Right.IsBlack()))
                    {
                        other.MakeNodeRed();
                        child = parent;
                    }
                    else
                    {
                        if (other.Right.IsBlack())
                        {
                            other.Left.MakeNodeBlack();
                            other.MakeNodeRed();
                            RotateRight(other);
                            other = parent.Right;
                        }
                        if (parent.IsRed())
                        {
                            other.MakeNodeRed();
                        }
                        else
                        {
                            other.MakeNodeBlack();
                        }
                        parent.MakeNodeBlack();
                        other.Right.MakeNodeBlack();
                        RotateLeft(parent);
                        child = Root;
                    }
                }
                else
                {
                    WeightedRedBlackTreeNode <K, V> other = parent.Left;
                    if (other.IsRed())
                    {
                        other.MakeNodeBlack();
                        parent.MakeNodeRed();
                        RotateRight(parent);
                        other = parent.Left;
                    }
                    if (other == null ||
                        (other.Right.IsBlack() &&
                         other.Left.IsBlack()))
                    {
                        other.MakeNodeRed();
                        child = parent;
                    }
                    else
                    {
                        if (other.Left.IsBlack())
                        {
                            other.Right.MakeNodeBlack();
                            other.MakeNodeRed();
                            RotateLeft(other);
                            other = parent.Left;
                        }
                        if (parent.IsRed())
                        {
                            other.MakeNodeRed();
                        }
                        else
                        {
                            other.MakeNodeBlack();
                        }
                        parent.MakeNodeBlack();
                        other.Left.MakeNodeBlack();
                        RotateRight(parent);
                        child = Root;
                    }
                }
                parent = child.Parent;
                if (child != Root)
                {
                    rightSide = (child == parent.Right);
                }
            }

            child.MakeNodeBlack();
        }
コード例 #2
0
        /// <summary>
        /// This corrects the tree for a newly-inserted node, rotating it as
        /// necessary to keep it balanced.  The algorithm is the same as RB-INSERT in [1],
        /// minus the first line that performs TREE-INSERT. O(lg n).
        /// </summary>
        /// <param name="node">The newly-inserted node.</param>
        protected void InsertFixup(WeightedRedBlackTreeNode <K, V> node)
        {
            node.MakeNodeRed();
            WeightedRedBlackTreeNode <K, V> parent = node.Parent;

            while (node != Root && parent.IsRed())
            {
                if (parent == parent.Parent.Left)
                {
                    WeightedRedBlackTreeNode <K, V> uncle = parent.Parent.Right;
                    if (uncle.IsRed())
                    {
                        parent.MakeNodeBlack();
                        uncle.MakeNodeBlack();
                        parent.Parent.MakeNodeRed();
                        node   = parent.Parent;
                        parent = node.Parent;
                    }
                    else
                    {
                        if (node == parent.Right)
                        {
                            node = parent;
                            RotateLeft(node);
                            parent = node.Parent;
                        }
                        parent.MakeNodeBlack();
                        parent.Parent.MakeNodeRed();
                        RotateRight(parent.Parent);
                        parent = node.Parent;
                    }
                }
                else
                {
                    WeightedRedBlackTreeNode <K, V> uncle = parent.Parent.Left;
                    if (uncle.IsRed())
                    {
                        parent.MakeNodeBlack();
                        uncle.MakeNodeBlack();
                        parent.Parent.MakeNodeRed();
                        node   = parent.Parent;
                        parent = node.Parent;
                    }
                    else
                    {
                        if (node == parent.Left)
                        {
                            node = parent;
                            RotateRight(node);
                            parent = node.Parent;
                        }
                        parent.MakeNodeBlack();
                        parent.Parent.MakeNodeRed();
                        RotateLeft(parent.Parent);
                        parent = node.Parent;
                    }
                }
            }

            Root.MakeNodeBlack();
        }