Пример #1
0
        private void RebalancePostInsertion(RBTreeNode newNode)
        {
            /**
             * Insert function places newNode as an appropriate leaf for a regular BST but
             * not necessarily a Red-black tree. Check if newNode's parent is RED (ie. if it
             * breaks a only red-black tree condition). If so, use the RED and BLACK labels
             * of newNode's parent, grandparent, and/or pibling (aunt/uncle) to balance.
             *
             * Note on conceptualizing this process:
             *  At this point, newNode is a RED leaf whose addition may cause the tree to
             *  not meet the required RED-BLACK conditions (noted in class description)
             *  such that it is imbalanced beyond the red-black tree threshold. In order
             *  to correct for this, we re-balance and/or recolor the subtree rooted at
             *  newNode's grandparent. We perform this process iteratively, reassigning
             *  newNode to its decendants (parents/grandparents), until we reach the root.
             *  At no point do we consider ancestors of newNode.
             *
             *  See this page for a more detailed overview of the process:
             *      https://www.geeksforgeeks.org/red-black-tree-set-2-insert/  */

            if (newNode.GrandParent() == null)
            {
                return;
            }

            RBTreeNode u;   // Will represent pibling (aunt/uncle) or parent of newNode.

            // ie. given newNode's grandparent (gP), u can be either gP's
            // left or right child

            while (newNode.Parent().IsRed())
            {
                // Case: p is the RIGHT child of gP:
                if (newNode.Parent() == newNode.GrandParent().Right())
                {
                    // Set u as the (LEFT) pibling of newNode
                    u = newNode.GrandParent().Left();

                    // Case: u exists and is RED: set both u & p to BLACK, set gP to RED,
                    // assign newNode = gP
                    if (u != null && u.IsRed())
                    {
                        u.SetBlack();
                        newNode.Parent().SetBlack();
                        newNode.GrandParent().SetRed();
                        newNode = newNode.GrandParent();
                    }
                    else      // Case: the (LEFT) pibling of newNode is BLACK

                    // Case: newNode is the left child of p: assign newNode = p and
                    // right rotate newNode
                    {
                        if (newNode == newNode.Parent().Left())
                        {
                            newNode = newNode.Parent();
                            RotateRight(newNode);
                        }

                        // Set p to BLACK and gP to RED. Then left rotate gP.
                        newNode.Parent().SetBlack();
                        newNode.GrandParent().SetRed();
                        RotateLeft(newNode.GrandParent());
                    }
                }
                else     // Case: p is the LEFT child of gP:

                // Assign u as the (RIGHT) pibling of newNode
                {
                    u = newNode.GrandParent().Right();

                    // Case: u is RED: set the color of both children of gP to BLACK, set
                    // gp to RED. Assign gP = newNode.
                    if (u != null && u.IsRed())
                    {
                        u.SetBlack();
                        newNode.Parent().SetBlack();
                        newNode.GrandParent().SetRed();
                        newNode = newNode.GrandParent();
                    }
                    else
                    {
                        // Case: newNode is the right child of p then: set p = newNode.
                        // Then left rotate newNode.
                        if (newNode == newNode.Parent().Right())
                        {
                            newNode = newNode.Parent();
                            RotateLeft(newNode);
                        }

                        // Set color of p as BLACK and color of gP as RED. Then right
                        // rotate gP.
                        newNode.Parent().SetBlack();
                        newNode.GrandParent().SetRed();
                        RotateRight(newNode.GrandParent());
                    }
                }

                if (newNode == Root)
                {
                    break;
                }
            }
            Root.SetBlack();
        }
Пример #2
0
        private void RebalancePostDeletion(RBTreeNode node)
        {
            // Very similar to RebalancePostInsertion function
            // node is the node in the location of/closest to the node just deleted
            RBTreeNode s; // represents sibbling of node

            while (node != Root && node.IsBlack())
            {
                if (node == node.Parent().Left())
                {
                    s = node.Parent().Right();

                    if (s.IsRed())   // case 1
                    {
                        s.SetBlack();
                        node.Parent().SetRed();
                        RotateLeft(node.Parent());
                        s = node.Parent().Right();
                    }

                    if (s.Left().IsBlack() && s.Right().IsBlack())   // case 2
                    {
                        s.SetRed();
                        node = node.Parent();
                    }
                    else
                    {
                        if (s.Right().IsBlack())   // case 3
                        {
                            s.Left().SetBlack();
                            s.SetRed();
                            RotateRight(s);
                            s = node.Parent().Right();
                        }

                        if (s.Parent().IsRed())
                        {
                            s.SetRed();
                        }
                        else
                        {
                            s.SetBlack();
                        }

                        node.Parent().SetBlack();
                        s.Right().SetBlack();
                        RotateLeft(s.Parent());
                        node = Root;
                    }
                }
                else
                {
                    s = node.Parent().Left();

                    if (s.IsRed())
                    {
                        s.SetBlack();
                        node.Parent().SetRed();
                        RotateRight(node.Parent());
                        s = node.Parent().Left();
                    }
                    if (s.Right() == null)
                    {
                        s.SetRight(Leaf);
                    }
                    if (s.Left() == null)
                    {
                        s.SetLeft(Leaf);
                    }
                    if (s.Right().IsBlack() && s.Left().IsBlack())
                    {
                        s.SetRed();
                        node = node.Parent();
                    }
                    else
                    {
                        if (s.Left().IsBlack())
                        {
                            s.Right().SetBlack();
                            s.SetRed();
                            RotateLeft(s);
                            s = node.Parent().Left();
                        }

                        if (s.Parent().IsRed())
                        {
                            s.SetRed();
                        }
                        else
                        {
                            s.SetBlack();
                        }

                        node.Parent().SetBlack();
                        s.Left().SetBlack();
                        RotateRight(node.Parent());
                        node = Root;
                    }
                }
            }
            node.SetBlack();
        }