示例#1
0
        public void Delete(RBTreeNode node, int value)
        {
            // Traverse until we find nodeToDelete
            RBTreeNode nodeToDelete = null;

            while (node != null)
            {
                if (node.GetData() == value)
                {
                    nodeToDelete = node;
                    break;
                }
                node = (value < node.GetData()) ? node.Left() : node.Right();
            }
            if (nodeToDelete == null)
            {
                throw new Exception("Cannot find node to delete with " +
                                    $"value {value} in Red Black Tree");
            }

            RBTreeNode x, y;

            // Save the color of nodeToDelete
            bool originallyRed = nodeToDelete.IsRed();

            // If nodeToDelete only has left children, replace with its left subtree
            if (nodeToDelete.Left() == null || nodeToDelete.Left().IsEmpty())
            {
                x = nodeToDelete.Right();
                if (x == null)
                {
                    x = Leaf;
                }
                Transplant(nodeToDelete, x);

                // If nodeToDelete only has right children, replace with its right subtree
            }
            else if (nodeToDelete.Right() == null || nodeToDelete.Right().IsEmpty())
            {
                x = nodeToDelete.Left();
                if (x == null)
                {
                    x = Leaf;
                }
                Transplant(nodeToDelete, x);
            }
            else        // nodeToDelete either has two children or is a leaf

            // y = smallest node whose value is greater than that of nodeToDelete
            // will replace nodeToDelete
            {
                y             = Minimum(nodeToDelete.Right());
                originallyRed = y.IsRed();

                // x = subtree root with values greater than y
                x = y.Right();
                if (x == null)
                {
                    x = Leaf;
                }

                // if y is a child of nodeToDelete, x is already stored in the right place
                if (y.Parent() == nodeToDelete)
                {
                    x.SetParent(y);
                }
                else     // else replace y with its right subtree and update attributes
                {
                    Transplant(y, y.Right());
                    y.SetRight(nodeToDelete.Right());
                    y.Right().SetParent(y);
                }

                // replace nodeToDelete with y and update attributes
                Transplant(nodeToDelete, y);
                y.SetLeft(nodeToDelete.Left());
                y.Left().SetParent(y);

                // y will replace nodeToDelete's location in tree, update its color
                if (originallyRed)
                {
                    y.SetRed();
                }
                else
                {
                    y.SetBlack();
                }
            }
            if (!(originallyRed))
            {
                RebalancePostDeletion(x);
            }
        }