Esempio n. 1
0
        /// <summary>
        /// Travel down the tree recursively, adding the node at the best leaf found.
        /// </summary>
        private PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > AddRecursive(T data, PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > currentNode)
        {
            PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > newNode = null;

            if (comparisonFunction(currentNode.Data.Data, data) > 0)
            {
                if (currentNode.Left == null)
                {
                    currentNode.Left = new PointerBackedBinaryTreeNode <RedBlackTreeNode <T> >(
                        new RedBlackTreeNode <T>(data, RedBlackTreeNode <T> .Red), currentNode);
                    newNode = currentNode.Left;
                }
                else
                {
                    newNode = this.AddRecursive(data, currentNode.Left);
                }
            }
            else
            {
                if (currentNode.Right == null)
                {
                    currentNode.Right = new PointerBackedBinaryTreeNode <RedBlackTreeNode <T> >(
                        new RedBlackTreeNode <T>(data, RedBlackTreeNode <T> .Red), currentNode);
                    newNode = currentNode.Right;
                }
                else
                {
                    newNode = this.AddRecursive(data, currentNode.Right);
                }
            }

            return(newNode);
        }
Esempio n. 2
0
 /// <summary>
 /// Creates a new binary tree node with the given data and parent node.
 /// </summary>
 public PointerBackedBinaryTreeNode(T data, PointerBackedBinaryTreeNode <T> parent)
 {
     this.Data   = data;
     this.Parent = parent;
     this.Left   = null;
     this.Right  = null;
 }
        public void GetSiblingFindsNoSiblingWhenNoneExists()
        {
            PointerBackedBinaryTreeNode <string> testNode = new PointerBackedBinaryTreeNode <string>("abc", null);

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

            Assert.IsNull(testNode.GetSibling());
            Assert.IsNull(testNode.Left.GetSibling());
        }
        public void GetSiblingFindsSibling()
        {
            PointerBackedBinaryTreeNode <string> testNode = new PointerBackedBinaryTreeNode <string>("abc", null);

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

            Assert.AreEqual(testNode.Right, testNode.Left.GetSibling());
            Assert.AreEqual(testNode.Left, testNode.Right.GetSibling());
        }
        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());
        }
        public void GetUncleFindsUncle()
        {
            PointerBackedBinaryTreeNode <string> testNode = new PointerBackedBinaryTreeNode <string>("abc", null);

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

            Assert.AreEqual(testNode.Right, testNode.Left.Left.GetUncle());

            testNode.Right.Left = new PointerBackedBinaryTreeNode <string>("lmn", testNode.Right);
            Assert.AreEqual(testNode.Left, testNode.Right.Left.GetUncle());
        }
Esempio n. 7
0
        /// <summary>
        /// Removes the specified node (the object itself) from the tree.
        /// </summary>
        /// <remarks>Duplicates according to <see cref="IComparable{T}"/> are ignored -- only the specified node is removed</remarks>
        /// <param name="node">The node to remove.</param>
        public void Remove(PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node), "Cannot remove a node which does not exist in the tree.");
            }

            PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > childNode;

            if (node.Left == null && node.Right == null)
            {
                // Node has no children, so remove it directly.
                if (node.Parent == null)
                {
                    this.Root = null;
                    return;
                }
                else
                {
                    this.SetParentPointer(node, null);
                }
            }
            else
            {
                // Delete node, replacing with child node.
                childNode        = node.Left == null ? node.Right : node.Left;
                childNode.Parent = node.Parent;
                if (node.Parent.Left == node)
                {
                    node.Parent.Left = childNode;
                }
                else
                {
                    node.Parent.Right = childNode;
                }

                // Clean up colors
                if (node.Data.IsBlack)
                {
                    // Switch red to black in the easy case.
                    if (!childNode.Data.IsBlack)
                    {
                        childNode.Data.IsBlack = true;
                    }
                    else
                    {
                        DeleteRepair(childNode);
                    }
                }
            }
        }
Esempio n. 8
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);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Returns the sibling of this node in the tree, null if there are no siblings.
        /// </summary>
        /// <remarks>
        /// Because this is a binary tree, there can only ever be one sibling.
        /// </remarks>
        public PointerBackedBinaryTreeNode <T> GetSibling()
        {
            PointerBackedBinaryTreeNode <T> sibling = null;

            if (this.Parent != null)
            {
                if (this.Parent.Left == this)
                {
                    sibling = this.Parent.Right;
                }
                else
                {
                    sibling = this.Parent.Left;
                }
            }

            return(sibling);
        }
Esempio n. 10
0
        /// <summary>
        /// Adds <paramref name="data"/> to the tree
        /// </summary>
        /// <param name="data">The data to add</param>
        /// <returns>The node containing the specified data</returns>
        public PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > Add(T data)
        {
            PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > newNode = null;

            if (this.Root == null)
            {
                this.Root = new PointerBackedBinaryTreeNode <RedBlackTreeNode <T> >(
                    new RedBlackTreeNode <T>(data, RedBlackTreeNode <T> .Red), null);
                newNode = this.Root;
            }
            else
            {
                newNode = this.AddRecursive(data, this.Root);
            }

            this.InsertRepair(newNode);

            return(newNode);
        }
Esempio n. 11
0
        /// <summary>
        /// Attempts to find the first node with the specified data. Returns <c>null</c> if no node was found.
        /// </summary>
        /// <param name="data">The data to find.</param>
        /// <returns>The node found, null if none found.</returns>
        public PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > Find(T data)
        {
            PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > currentNode = this.Root;

            while (currentNode != null)
            {
                int comparisonResult = comparisonFunction(currentNode.Data.Data, data);
                if (comparisonResult > 0)
                {
                    currentNode = currentNode.Left;
                }
                else if (comparisonResult == 0)
                {
                    // Found the node we want!
                    break;
                }
                else
                {
                    currentNode = currentNode.Right;
                }
            }

            return(currentNode);
        }
Esempio n. 12
0
        private void DeleteRepair(PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > node)
        {
            if (node.Parent != null)
            {
                // If this node isn't the root, we need to...
                PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > sibling = node.GetSibling();
                if (!sibling.Data.IsBlack)
                {
                    // ... reverse colors
                    sibling.Parent.Data.IsBlack = false;
                    sibling.Data.IsBlack        = true;

                    // .... and rotate around
                    if (node.Parent.Left == node)
                    {
                        this.RotateLeft(node.Parent);
                    }
                    else
                    {
                        this.RotateRight(node.Parent);
                    }
                }

                // Once we do that, we need to possibly ...
                if (sibling.Data.IsBlack && sibling.Left.Data.IsBlack && sibling.Right.Data.IsBlack)
                {
                    // ... repeat recursivly or color theparent
                    sibling.Data.IsBlack = false;
                    if (node.Parent.Data.IsBlack)
                    {
                        DeleteRepair(node.Parent);
                    }
                    else
                    {
                        node.Parent.Data.IsBlack = false;
                    }
                }
                else
                {
                    // ... or perform more rotations with coloration swaps
                    if (sibling.Data.IsBlack)
                    {
                        // Force subsequent rotations to 'do the right thing'
                        if (node.Parent.Left == node && sibling.Right.Data.IsBlack && !sibling.Left.Data.IsBlack)
                        {
                            sibling.Data.IsBlack      = false;
                            sibling.Left.Data.IsBlack = true;
                            this.RotateRight(sibling);
                        }
                        else if (node.Parent.Right == node && sibling.Left.Data.IsBlack && !sibling.Right.Data.IsBlack)
                        {
                            sibling.Data.IsBlack       = false;
                            sibling.Right.Data.IsBlack = true;
                            this.RotateLeft(sibling);
                        }
                    }

                    sibling.Data.IsBlack     = node.Parent.Data.IsBlack;
                    node.Parent.Data.IsBlack = true;

                    if (node.Parent.Left == node)
                    {
                        sibling.Right.Data.IsBlack = true;
                        this.RotateLeft(node.Parent);
                    }
                    else
                    {
                        sibling.Left.Data.IsBlack = true;
                        this.RotateRight(node.Parent);
                    }
                }
            }
            else
            {
                this.Root = node;
            }
        }