Esempio n. 1
0
        /// <summary>
        /// Ensures the tree follows red-black properties after an insertion of the given node.
        /// </summary>
        private void InsertRepair(PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > currentNode)
        {
            if (currentNode.Parent == null)
            {
                // If this is the root node, it must be black. It will currently be red, because
                //  that is the color new nodes are added as.
                currentNode.Data.IsBlack = true;
            }
            else if (currentNode.Parent.Data.IsBlack)
            {
                // If the parent node is black, the red-black ordering isn't invalidated, so do nothing.
            }
            else if (currentNode.GetUncle()?.Data.IsBlack == false)
            {
                // There is a red uncle (and the current node is red), so we can switch then both to black with the
                //  grandparent becoming red. This may violate #2, so we need to rerun the recursion.
                currentNode.Parent.Data.IsBlack = true;
                currentNode.GetUncle().Data.IsBlack = true;

                // Because we found an uncle, a grandparent is guaranteed to exist.
                currentNode.Parent.Parent.Data.IsBlack = false;
                InsertRepair(currentNode.Parent.Parent);
            }
            else // parent is red, uncle is black or missing, grandparent definitely exists.
            {
                // Rotate left or right and then reverse the rotation later to effectively switch nodes around
                // and satisfy red-black height and color properties
                if (currentNode == currentNode.Parent.Right && currentNode.Parent == currentNode.Parent.Parent.Left)
                {
                    this.RotateLeft(currentNode.Parent);
                    currentNode = currentNode.Left;

                    currentNode.Parent.Data.IsBlack        = true;
                    currentNode.Parent.Parent.Data.IsBlack = false;

                    this.RotateRight(currentNode.Parent.Parent);
                }
                else if (currentNode == currentNode.Parent.Left && currentNode.Parent == currentNode.Parent.Parent.Right)
                {
                    this.RotateRight(currentNode.Parent);
                    currentNode = currentNode.Right;

                    currentNode.Parent.Data.IsBlack        = true;
                    currentNode.Parent.Parent.Data.IsBlack = false;

                    this.RotateLeft(currentNode.Parent.Parent);
                }
            }
        }
        public void GetUncleFindsNoUncleWhenNoneExists()
        {
            PointerBackedBinaryTreeNode <string> testNode = new PointerBackedBinaryTreeNode <string>("abc", null);

            Assert.IsNull(testNode.GetUncle());

            testNode.Left      = new PointerBackedBinaryTreeNode <string>("def", testNode);
            testNode.Left.Left = new PointerBackedBinaryTreeNode <string>("geh", testNode.Left);

            Assert.IsNull(testNode.Left.GetUncle());
            Assert.IsNull(testNode.Left.Left.GetUncle());
        }