private static void HandleBlackUncle(IBinarySearchTreeNode <T> newNode, IBinarySearchTreeNode <T> parent, IBinarySearchTreeNode <T> uncle, IBinarySearchTreeNode <T> grandparent)
        {
            if (IsLeft(newNode))
            {
                if (IsLeft(parent))
                {
                    // Case A: the new node and its parent are left children
                    IBinarySearchTreeNode <T> tmp = parent.Right;
                    parent.Parent           = grandparent.Parent;
                    parent.Right            = grandparent;
                    grandparent.Parent      = parent;
                    grandparent.Left        = tmp;
                    grandparent.Left.Parent = grandparent;

                    parent.IsBlack      = true;
                    grandparent.IsBlack = false;
                }
                else
                {
                }
            }
            else
            {
            }
        }
Beispiel #2
0
        private static bool UnoptimizedValidateSearchTree(IBinarySearchTreeNode <T> rootNode)
        {
            // Base case - no children
            if (rootNode.Degree == 0)
            {
                return(true);
            }

            // Binary search tree - all values in nodes left of the
            // current node must be smaller or equal.
            if (rootNode.Left?.FindMax().CompareTo(rootNode.Data) > 0)
            {
                return(false);
            }

            // Binary search tree - all values in nodes right of the
            // current node must be greater.
            if (rootNode.Right?.FindMin().CompareTo(rootNode.Data) < 1)
            {
                return(false);
            }

            // Else, check children sub-trees.
            var leftState = rootNode.Left == null ||
                            rootNode.Left.IsValidSearchTree;

            var rightState = rootNode.Right == null ||
                             rootNode.Right.IsValidSearchTree;

            return(leftState && rightState);
        }
 private void NonRecursiveInsert(IBinarySearchTreeNode <TKey, TValue> root, IBinarySearchTreeNode <TKey, TValue> newNode)
 {
     while (true)
     {
         if (root.Key.CompareTo(newNode.Key) > 0)
         {
             if (root.LeftChild == null)
             {
                 root.LeftChild = newNode;
                 return;
             }
             else
             {
                 root = root.LeftChild;
             }
         }
         else
         {
             if (root.RightChild == null)
             {
                 root.RightChild = newNode;
                 return;
             }
             else
             {
                 root = root.RightChild;
             }
         }
     }
 }
        private static void Balance(IBinarySearchTreeNode <T> newNode)
        {
            IBinarySearchTreeNode <T> parent = newNode.Parent;

            if (parent != null)
            {
                if (!parent.IsBlack) // We have a red violation
                {
                    IBinarySearchTreeNode <T> uncle       = GetSibling(parent);
                    IBinarySearchTreeNode <T> grandparent = parent.Parent; // Since we know that the parent is red and that the tree was previously balances the grandparent must exist
                    if (uncle == null || uncle.IsBlack)
                    {
                        HandleBlackUncle(newNode, parent, uncle, grandparent);
                    }
                    else
                    {
                        HandleRedUncle(parent, uncle, grandparent);
                    }
                }
                // else the parent node of the new node is black and the tree is already balanced
            }
            else
            {
                // this must be the root node, ensure it is black
                newNode.IsBlack = true;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Find a node
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        IBinarySearchTreeNode <T> IBinarySearchTree <T> .FindNode(T Value)
        {
            //Root itself is null
            if (_root == null)
            {
                return(null);
            }

            IBinarySearchTreeNode <T> current = _root;

            while (current != null)
            {
                if (current.Data.CompareTo(Value) == 0)
                {
                    break;
                }
                else if (current.Data.CompareTo(Value) > 0)
                {
                    current = current.LeftChild;
                }
                else
                {
                    current = current.RightChild;
                }
            }

            return(current);
        }
 private void Insert(IBinarySearchTreeNode <TKey, TValue> root, IBinarySearchTreeNode <TKey, TValue> newNode)
 {
     if (root.Key.CompareTo(newNode.Key) > 0)
     {
         if (root.LeftChild == null)
         {
             root.LeftChild = newNode;
         }
         else
         {
             Insert(root.LeftChild, newNode);
         }
     }
     else
     {
         if (root.RightChild == null)
         {
             root.RightChild = newNode;
         }
         else
         {
             Insert(root.RightChild, newNode);
         }
     }
 }
        private bool Remove(IBinarySearchTreeNode <TKey, TValue> parent, TKey key)
        {
            if (parent == null)
            {
                return(false);
            }

            if (parent.Key.CompareTo(key) > 0)
            {
                if (parent.LeftChild != null && parent.LeftChild.Key.CompareTo(key) == 0)
                {
                    parent.LeftChild = GetNewChildAfterRemoving(parent.LeftChild);
                    return(true);
                }
                else
                {
                    return(Remove(parent.LeftChild, key));
                }
            }
            else
            {
                // if (parent.Key.CompareTo(key) < 0)
                // we exclude case where parent.Key.CompareTo(key) == 0 in the public Remove(key) method
                if (parent.RightChild != null && parent.RightChild.Key.CompareTo(key) == 0)
                {
                    parent.RightChild = GetNewChildAfterRemoving(parent.RightChild);
                    return(true);
                }
                else
                {
                    return(Remove(parent.RightChild, key));
                }
            }
        }
        public void Add(T value)
        {
            if (Count == Int32.MaxValue)
            {
                throw new CollectionFullException();
            }

            if (_root == null)
            {
                _root         = new BinarySearchTreeNode <T>(value);
                _root.IsBlack = true; // ensure root node is still black
            }
            else
            {
                _root.AddChild(value);

                // We need to make sure that _root is still the root
                while (_root.Parent != null)
                {
                    _root = _root.Parent;
                }
            }

            Count++;
        }
        public void BinarySearchTreeTests_SearchTest()
        {
            IBinarySearchTree <int, int> tree = new BinarySearchTree <int, int>();

            IBinarySearchTreeNode <int, int> actual = tree.Search(100);

            Assert.IsNull(actual);
        }
        private static void HandleRedUncle(IBinarySearchTreeNode <T> parent, IBinarySearchTreeNode <T> uncle, IBinarySearchTreeNode <T> grandparent)
        {
            parent.IsBlack      = true;
            uncle.IsBlack       = true;
            grandparent.IsBlack = false;

            Balance(grandparent);
        }
Beispiel #11
0
        /// <summary>
        /// Find some data in a binary search tree using binary search.
        /// </summary>
        /// <param name="data">
        /// The data to search for.
        /// </param>
        /// <param name="lastNodeVisited">
        /// Will be filled with the last node visited. If the return value
        /// is "true" than this is the matching node or result.
        /// In case of "false" this is the last node investigated before
        /// stopping the search. Having this reference is essential
        /// for node insertion and removal scenarios.
        /// </param>
        /// <param name="safetyCheck">
        /// Check whether the (sub-)tree is a valid binary search tree
        /// at all before searching. Throws <see cref="InvalidOperationException"/>
        /// if invalid. This is a costly operation of O(n)
        /// for valid trees but spares you an extra check of
        /// "IsValidSearchTree" if you had done so anyway.
        /// </param>
        /// <returns>
        /// True if the data was found otherwise false.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown if the (sub-)tree is not a valid binary search tree by
        /// definition AND "safetyCheck" was set to "true".
        /// </exception>
        public bool Find(T data, out IBinarySearchTreeNode <T> lastNodeVisited, bool safetyCheck = false)
        {
            lastNodeVisited = this;

            Debug.WriteLine($"BST {nameof(Find)}: Searching for '{data}' from '{this}' ...");

            // Safety check requested - won't search an invalid BST
            if (safetyCheck)
            {
                if (!IsValidSearchTree)
                {
                    throw new InvalidOperationException(
                              $"{nameof(IBinarySearchTreeNode<T>)}.{nameof(Find)}: "
                              + $"This is an invalid binary search tree and {nameof(safetyCheck)} was set to {true}. "
                              + "Search aborted.");
                }
            }

            // Data found
            if (data.CompareTo(Data) == 0)
            {
                Debug.WriteLine($"BST {nameof(Find)}: Data ({data}) match found!");

                return(true);
            }

            // Supplied data is lesser than current node's data
            if (data.CompareTo(Data) < 0)
            {
                Debug.WriteLine($"BST {nameof(Find)}: {(this.Left == null ? "No left child." : "Search left sub-tree ...")}");

                // Lesser means we have to go left
                // If there isn't a left node the data could not be found.
                return
                    (this.Left == null
                        ? false
                        : this.Left.Find(data, out lastNodeVisited));
            }

            // Supplied data is greater than current node's data
            if (data.CompareTo(Data) > 0)
            {
                Debug.WriteLine($"BST {nameof(Find)}: {(this.Right == null ? "No right child." : "Search right sub-tree ...")}");

                // Greater means we have to go right
                // If there isn't a right node the data could not be found.
                return
                    (this.Right == null
                        ? false
                        : this.Right.Find(data, out lastNodeVisited));
            }

            Debug.WriteLine($"BST {nameof(Find)}: Search for '{data}' unsuccessful.");

            return(false);
        }
        private int GetHeight(IBinarySearchTreeNode <TKey, TValue> root)
        {
            if (root == null)
            {
                return(0);
            }

            return(Math.Max(
                       root.LeftChild != null ? 1 + GetHeight(root.LeftChild) : 0,
                       root.RightChild != null ? 1 + GetHeight(root.RightChild) : 0));
        }
        private void TraverseInOrder(IBinarySearchTreeNode <TKey, TValue> root, Action <IBinarySearchTreeNode <TKey, TValue> > yielder)
        {
            if (root == null)
            {
                return;
            }

            TraverseInOrder(root.LeftChild, yielder);
            yielder(root);
            TraverseInOrder(root.RightChild, yielder);
        }
Beispiel #14
0
 private static bool CheckNodeArgument <T>(IBinarySearchTreeNode <T> node)
     where T : IComparable <T>
 {
     if (node == null)
     {
         throw new ArgumentNullException(nameof(node));
     }
     else
     {
         return(true);
     }
 }
Beispiel #15
0
        /// <summary>
        /// Simple binary search tree demos examining various BSTs.
        /// </summary>
        private static void SampleBinarySearchTreeDemos()
        {
            IBinarySearchTreeNode <int> resultNode = null;
            var result = false;

            WriteLine("SAMPLE BINARY SEARCH TREE DEMOS");
            WriteLine();

            var invalidTree = CreateBookSampleBinarySearchTree();

            WriteLine(invalidTree);

            WriteLine($"Is valid BST? {invalidTree.Root.IsValidSearchTree}");

            WriteLine();
            WriteLine();

            var validTree1 = CreateValidBinarySearchTree1();

            WriteLine(validTree1);

            WriteLine($"Is valid BST? {validTree1.Root.IsValidSearchTree}");

            var v1data1 = 47;
            var v1data2 = 43;

            result = validTree1.Root.Find(v1data1, out resultNode);
            WriteLine($"Search for {v1data1}: Found = {result}, Node = '{resultNode}'.");

            result = validTree1.Root.Find(v1data2, out resultNode);
            WriteLine($"Search for {v1data2}: Found = {result}, Node = '{resultNode}'.");

            WriteLine();
            WriteLine();

            var validTree2 = CreateValidBinarySearchTree2();

            WriteLine(validTree2);

            WriteLine($"Is valid BST? {validTree2.Root.IsValidSearchTree}");

            var v2data1 = 60;
            var v2data2 = 73;

            result = validTree2.Root.Find(v2data1, out resultNode);
            WriteLine($"Search for {v2data1}: Found = {result}, Node = '{resultNode}'.");

            result = validTree2.Root.Find(v2data2, out resultNode);
            WriteLine($"Search for {v2data2}: Found = {result}, Node = '{resultNode}'.");

            WriteLine();
        }
        public void BinarySearchTreeTests_LCA3()
        {
            IBinarySearchTree <int, string> tree = new BinarySearchTree <int, string>();

            IBinarySearchTreeNode <int, string> john  = tree.Insert(10, "John");
            IBinarySearchTreeNode <int, string> clark = tree.Insert(5, "Clark");
            IBinarySearchTreeNode <int, string> pitty = tree.Insert(13, "Pitty");

            IBinarySearchTreeNode <int, string> ancestor = tree.LCA(john, john);

            Assert.IsNotNull(ancestor);
            Assert.AreEqual(john, ancestor);
        }
        public IBinarySearchTreeNode <TKey, TValue> LCA(IBinarySearchTreeNode <TKey, TValue> node1, IBinarySearchTreeNode <TKey, TValue> node2)
        {
            // we assume that node1 and node2  have already placed in the tree

            if (node1.Key.CompareTo(node2.Key) > 0)
            {
                IBinarySearchTreeNode <TKey, TValue> tmp = node1;
                node1 = node2;
                node2 = tmp;
            }

            return(LCA(root, node1, node2));
        }
        public bool Remove(TKey key)
        {
            if (root == null)
            {
                return(false);
            }

            if (root.Key.CompareTo(key) == 0)
            {
                root = GetNewChildAfterRemoving(root);
                return(true);
            }

            return(Remove(root, key));
        }
Beispiel #19
0
        /// <summary>
        /// Find the maximum value below this node
        /// </summary>
        /// <param name="Node"></param>
        /// <returns></returns>
        public IBinarySearchTreeNode <T> FindMaxNode(IBinarySearchTreeNode <T> Node)
        {
            if (Node == null)
            {
                return(null);
            }

            IBinarySearchTreeNode <T> current = Node;

            while (current.HasRightChild)
            {
                current = current.RightChild;
            }

            return(current);
        }
Beispiel #20
0
        public void AddFirstNodeTest()
        {
            ITree <int> tree = new BinarySearchTree <int>();

            tree.Add(1);

            Assert.Equal(1, tree.Count);
            Assert.Equal(1, tree.Root.Value);

            IBinarySearchTreeNode <int> rootNode = (IBinarySearchTreeNode <int>)tree.Root;

            Assert.True(rootNode.IsBlack);

            Assert.Null(rootNode.Left);
            Assert.Null(rootNode.Right);
        }
Beispiel #21
0
        /// <summary>
        /// Find the smallest data value in a binary search (sub)-tree.
        /// </summary>
        /// <typeparam name="T">
        /// The type of data contained in the node.
        /// </typeparam>
        /// <param name="node">
        /// The start node to search recursively.
        /// </param>
        /// <returns>
        /// The smallest object by comparison.
        /// </returns>
        public static T FindMin <T>(this IBinarySearchTreeNode <T> node)
            where T : IComparable <T>
        {
            CheckNodeArgument(node);

            // In-order traversal of a binary search tree yields a list
            // of sorted values.
            // This could also enable checks in alternate ways.
            var nodes = node.Traverse(TreeTraversalMode.InOrder);

            // We could take the first item in the list for min but just
            // to be sure, it might be an invalid BST, take it explicitly.
            return(nodes
                   .Select(n => n.Data)
                   .Min());
        }
        public virtual IBinarySearchTreeNode <TKey, TValue> Insert(TKey key, TValue value)
        {
            IBinarySearchTreeNode <TKey, TValue> newNode = new BinarySearchTreeNode <TKey, TValue>(key, value);

            if (root == null)
            {
                root = newNode;
            }
            else
            {
                // Insert(root, newNode);
                NonRecursiveInsert(root, newNode);
            }

            return(newNode);
        }
        private void Mirror(IBinarySearchTreeNode <TKey, TValue> root)
        {
            if (root == null)
            {
                return;
            }

            Mirror(root.LeftChild);
            Mirror(root.RightChild);

            // swap left and right subtree
            IBinarySearchTreeNode <TKey, TValue> tmp = root.LeftChild;

            root.LeftChild  = root.RightChild;
            root.RightChild = tmp;
        }
Beispiel #24
0
        public void RedViolationTest_BlackUncle_LeftNode_LeftParent()
        {
            // Test for Case A: the new node and its parent are left children

            ITree <int> tree = new BinarySearchTree <int>();

            // In order to easily simulate this case we are going to manually create the tree
            // so it is in the correct state.

            tree.Add(4);
            IBinarySearchTreeNode <int> rootNode = (IBinarySearchTreeNode <int>)tree.Root;

            rootNode.IsBlack            = true;
            rootNode.Right              = new BinarySearchTreeNode <int>(5);
            rootNode.Right.IsBlack      = true;
            rootNode.Right.Parent       = rootNode;
            rootNode.Left               = new BinarySearchTreeNode <int>(2);
            rootNode.Left.Parent        = rootNode;
            rootNode.Left.Right         = new BinarySearchTreeNode <int>(3);
            rootNode.Left.Right.IsBlack = true;
            rootNode.Left.Right.Parent  = rootNode.Left;

            tree.Add(1);

            rootNode = (IBinarySearchTreeNode <int>)tree.Root;
            Assert.Null(rootNode.Parent);
            Assert.Equal(2, rootNode.Value);
            Assert.True(rootNode.IsBlack);

            Assert.Equal(1, rootNode.Left.Value);
            Assert.False(rootNode.Left.IsBlack);
            Assert.Null(rootNode.Left.Left);
            Assert.Null(rootNode.Left.Right);

            Assert.Equal(4, rootNode.Right.Value);
            Assert.False(rootNode.Left.IsBlack);

            Assert.Equal(3, rootNode.Right.Left.Value);
            Assert.True(rootNode.Right.Left.IsBlack);
            Assert.Null(rootNode.Right.Left.Left);
            Assert.Null(rootNode.Right.Left.Right);

            Assert.Equal(5, rootNode.Right.Right.Value);
            Assert.True(rootNode.Right.Right.IsBlack);
            Assert.Null(rootNode.Right.Right.Left);
            Assert.Null(rootNode.Right.Right.Right);
        }
        private static IBinarySearchTreeNode <T> GetSibling(IBinarySearchTreeNode <T> node)
        {
            IBinarySearchTreeNode <T> sibling = null;

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

            return(sibling);
        }
        public void BinarySearchTreeTests_SimpleTree_SearchTest()
        {
            IBinarySearchTree <int, string> tree = new BinarySearchTree <int, string>();

            tree.Insert(10, "John");
            tree.Insert(5, "Clark");
            tree.Insert(13, "Pitty");

            IBinarySearchTreeNode <int, string> actual  = tree.Search(5);
            IBinarySearchTreeNode <int, string> actual2 = tree.Search(13);
            IBinarySearchTreeNode <int, string> actual3 = tree.Search(10);
            IBinarySearchTreeNode <int, string> actual4 = tree.Search(0);

            Assert.IsTrue(actual.Key == 5 && actual.Value == "Clark");
            Assert.IsTrue(actual2.Key == 13 && actual2.Value == "Pitty");
            Assert.IsTrue(actual3.Key == 10 && actual3.Value == "John");
            Assert.IsNull(actual4);
        }
        public void BinarySearchTreeTests_LCA5()
        {
            IBinarySearchTree <int, string>     tree  = new BinarySearchTree <int, string>();
            IBinarySearchTreeNode <int, string> lui   = tree.Insert(3, "Lui");
            IBinarySearchTreeNode <int, string> clark = tree.Insert(5, "Clark");
            IBinarySearchTreeNode <int, string> joney = tree.Insert(1, "Joney");
            IBinarySearchTreeNode <int, string> jack  = tree.Insert(8, "Jack");
            IBinarySearchTreeNode <int, string> john  = tree.Insert(10, "John");
            IBinarySearchTreeNode <int, string> ben   = tree.Insert(6, "Ben");
            IBinarySearchTreeNode <int, string> lulu  = tree.Insert(7, "Lu-lu");
            IBinarySearchTreeNode <int, string> cris  = tree.Insert(2, "Cris");
            IBinarySearchTreeNode <int, string> lenon = tree.Insert(0, "Lenon");

            IBinarySearchTreeNode <int, string> ancestor = tree.LCA(lulu, john);

            Assert.IsNotNull(ancestor);
            Assert.AreEqual(jack, ancestor);
        }
        protected virtual IBinarySearchTreeNode <TKey, TValue> Search(IBinarySearchTreeNode <TKey, TValue> root, TKey key)
        {
            if (root == null)
            {
                return(null);
            }

            int compareResult = root.Key.CompareTo(key);

            if (compareResult > 0)
            {
                return(Search(root.LeftChild, key));
            }
            else if (compareResult < 0)
            {
                return(Search(root.RightChild, key));
            }

            return(root);
        }
Beispiel #29
0
        /// <summary>
        /// Remove a node from the Binary search tree
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        IBinarySearchTreeNode <T> IBinarySearchTree <T> .RemoveNode(T Value)
        {
            IBinarySearchTreeNode <T> CurrentNode = (this as IBinarySearchTree <T>).FindNode(Value);

            if (CurrentNode == null)
            {
                return(null);
            }

            IBinarySearchTreeNode <T> Parent = CurrentNode.Parent;

            if (CurrentNode.ChildrenCount == 2)                                            // Has both left and right children
            {
                IBinarySearchTreeNode <T> temp = this.FindMinNode(CurrentNode.RightChild); //find minimum in right subtree
                CurrentNode.Data       = temp.Data;                                        //copy the value in the minimum to current
                CurrentNode.RightChild = temp.RightChild;                                  //delete the node with single child
            }
            else if (CurrentNode.HasLeftChild)                                             //Only has left child
            {
                CurrentNode.Parent.LeftChild = CurrentNode.LeftChild;
                CurrentNode.LeftChild.Parent = CurrentNode.Parent;
            }
            else if (CurrentNode.HasRightChild) //Only has right child
            {
                CurrentNode.Parent.RightChild = CurrentNode.RightChild;
                CurrentNode.RightChild.Parent = CurrentNode.Parent;
            }
            else //No children
            {
                if (CurrentNode.Parent.LeftChild == CurrentNode)
                {
                    CurrentNode.Parent.LeftChild = null;
                }
                else if (CurrentNode.Parent.RightChild == CurrentNode)
                {
                    CurrentNode.Parent.RightChild = null;
                }
            }

            return(CurrentNode);
        }
        private IBinarySearchTreeNode <TKey, TValue> GetNewChildAfterRemoving(IBinarySearchTreeNode <TKey, TValue> removedNode)
        {
            if (!removedNode.HasChildren)
            {
                return(null);
            }
            else
            {
                if (removedNode.LeftChild == null)
                {
                    return(removedNode.RightChild);
                }
                else if (removedNode.RightChild == null)
                {
                    return(removedNode.LeftChild);
                }
                else // has two children
                {
                    IBinarySearchTreeNode <TKey, TValue> parent = removedNode;
                    IBinarySearchTreeNode <TKey, TValue> leftmostNodeInTheRightSubtree = removedNode.RightChild;
                    while (leftmostNodeInTheRightSubtree.LeftChild != null)
                    {
                        parent = leftmostNodeInTheRightSubtree;
                        leftmostNodeInTheRightSubtree = leftmostNodeInTheRightSubtree.LeftChild;
                    }

                    if (parent != removedNode)
                    {
                        // leftmostNodeInTheRightSubtree may has ONLY a right child
                        // we was moving to the left all the time,
                        // thus we have to set a new left child for parent of leftmostNodeInTheRightSubtree
                        parent.LeftChild = leftmostNodeInTheRightSubtree.RightChild;
                        leftmostNodeInTheRightSubtree.RightChild = removedNode.RightChild;
                    }

                    leftmostNodeInTheRightSubtree.LeftChild = removedNode.LeftChild;

                    return(leftmostNodeInTheRightSubtree);
                }
            }
        }