Esempio n. 1
0
        public void DeleteLeaf(IBinaryTreeNode v)
        {
            if (!IsLeaf(v))
            {
                throw new ArgumentException("Node is not a leaf");
            }
            if (IsRoot(v))
            {
                SetRoot(null);
                return;
            }

            if (((BinaryTreeNode)v).Parent.RightChild == v)
            {
                ((BinaryTreeNode)v).Parent.RightChild = null;
            }
            else if (((BinaryTreeNode)v).Parent.LeftChild == v)
            {
                ((BinaryTreeNode)v).Parent.LeftChild = null;
            }
            else
            {
                throw new Exception("Tree messed up");
            }
        }
Esempio n. 2
0
 internal BinaryTree(IBinaryTreeNode <T> root, int nodeCount, int depth, BinaryTreeType type)
 {
     Root      = root;
     NodeCount = nodeCount;
     Depth     = depth;
     Type      = type;
 }
Esempio n. 3
0
 public static IBinaryTreeNode <TItem> Node <TItem>(
     TItem item,
     IBinaryTreeNode <TItem> left,
     IBinaryTreeNode <TItem> right)
 {
     return(new BinaryTreeNode <TItem>(item, left, right));
 }
Esempio n. 4
0
        private IBinaryTreeNode <T> FindWithParent(T item, out IBinaryTreeNode <T> parent)
        {
            IBinaryTreeNode <T> current = _head;

            parent = null;

            while (current != null)
            {
                var res = current.CompareTo(item);
                if (res > 0)
                {
                    parent  = current;
                    current = current.Left;
                }
                else if (res < 0)
                {
                    parent  = current;
                    current = current.Right;
                }
                else
                {
                    break;
                }
            }
            return(current);
        }
Esempio n. 5
0
        /// <summary>
        /// Applies rebalances after inserts
        /// </summary>
        /// <param name="node">Newly isnerted node</param>
        private void RebalanceAfterInsert(IBinaryTreeNode <TKey, TValue> node)
        {
            IBinaryTreeNode <TKey, TValue> current = node.Parent;

            while (current != null)
            {
                long balance = current.GetBalance();
                switch (balance)
                {
                case -2:
                case 2:
                    this.Rebalance(current, balance);
                    break;

                case -1:
                case 0:
                case 1:
                    //Balanced
                    break;

                default:
                    throw new InvalidOperationException("Illegal AVL Tree state");
                }
                current = current.Parent;
            }
        }
Esempio n. 6
0
        private static void FormatBinaryTreeNode(IBinaryTreeNode node, StringBuilder sb, string prefix, int level)
        {
            sb.Append("  ");

            for (int i = 0; i < level; i++)
            {
                sb.Append("  ");
            }

            if (!IsNullOrEmpty(prefix))
            {
                sb.AppendFormat("{0}: ", prefix);
            }

            if (node == null)
            {
                sb.Append("(null)\r\n");
            }
            else
            {
                sb.AppendFormat("{0}\r\n", Value(node.Value));

                if (node.Left != null || node.Right != null)
                {
                    FormatBinaryTreeNode(node.Right, sb, "RIGHT", level + 1);
                    FormatBinaryTreeNode(node.Left, sb, "LEFT", level + 1);
                }
            }
        }
Esempio n. 7
0
        public ITraversableTreeNode <T>?Transform <T>(IBinaryTreeNode <T>?root)
        {
            if (root == null)
            {
                return(null);
            }

            ITraversableTreeNode <T> newNode = new TreeNode <T>(root.Value);

            var leftSubTree = Transform(root.Left);

            if (leftSubTree != null)
            {
                newNode.Children.Add(leftSubTree);
            }

            var rightSubTree = Transform(root.Right);

            if (rightSubTree != null)
            {
                newNode.Children.Add(rightSubTree);
            }

            return(newNode);
        }
Esempio n. 8
0
        /// <summary>
        /// Removes the key-value pair at the given index
        /// </summary>
        /// <param name="index">Index</param>
        public void RemoveAt(int index)
        {
            IBinaryTreeNode <TKey, TValue> node = this.MoveToIndex(index);
            int c = node.Parent != null?this._comparer.Compare(node.Key, node.Parent.Key) : 0;

            this.RemoveNode(node, c);
        }
Esempio n. 9
0
 /// <summary>
 /// Isolates a Node from the tree by setting its parent and child links to be null
 /// </summary>
 /// <typeparam name="TKey">Key Type</typeparam>
 /// <typeparam name="TValue">Valye Type</typeparam>
 /// <param name="node">Node</param>
 /// <returns></returns>
 internal static IBinaryTreeNode <TKey, TValue> Isolate <TKey, TValue>(this IBinaryTreeNode <TKey, TValue> node)
 {
     node.Parent     = null;
     node.LeftChild  = null;
     node.RightChild = null;
     return(node);
 }
        public IBinaryTreeNode <T> InsertAfter(T value, IBinaryTreeNode <T> node)
        {
            this.EnsureNewValue(value);
            this.EnsureCurrentNode(node);

            var pivotNode    = ( Node )node;
            var leftmostNode = (pivotNode.Right != null) ? pivotNode.Right.GetLeftmost() : null;
            var oldRootNode  = m_rootNode;
            var parentNode   = leftmostNode ?? pivotNode;
            var newNode      = this.CreateNode(value);

            if (newNode == null)
            {
                throw new InvalidOperationException("A node was not created.");
            }

            if (leftmostNode != null)
            {
                parentNode.Left = newNode;
            }
            else
            {
                parentNode.Right = newNode;
            }

            newNode.Parent = parentNode;

            this.BalanceUp(parentNode);
            this.SetRootNodeColor();
            this.OnPostInsert(newNode, oldRootNode);

            return(newNode);
        }
Esempio n. 11
0
        /// <summary>
        ///     Internal method for searching a <paramref name="data"/> in subtree <paramref name="node"/>
        /// </summary>
        /// <param name="node">Subtree where to search</param>
        /// <param name="data">A value to search</param>
        /// <returns><see langword="true"/> if <paramref name="data"/> exists in subtree</returns>
        private bool InternalContains(IBinaryTreeNode <T> node, T data)
        {
            while (true)
            {
                if (ReferenceEquals(node, null))
                {
                    return(false);
                }

                switch (node.Data.CompareTo(data))
                {
                case 0:
                    return(true);

                case 1:
                    node = node.Left;

                    continue;

                default:
                    node = node.Right;

                    break;
                }
            }
        }
Esempio n. 12
0
        public static BinaryTreeNodeSaver <T> GetTreeSaverNode <T>(IBinaryTreeNode <T> Root, ref int MaxOffset, ref T MaxData, List <BinaryTreeNodeSaver <T> > Result = null)
        {
            var Res = new BinaryTreeNodeSaver <T>(Root);

            Result?.Add(Res);
            List <BinaryTreeNodeSaver <T> > Saver = new List <BinaryTreeNodeSaver <T> >();

            Saver.Add(Res);
            List <BinaryTreeNodeSaver <T> > Buf = new List <BinaryTreeNodeSaver <T> >();

            //Res.Update(Buf, ref MaxOffset, ref MaxData);
            do
            {
                foreach (var v in Saver)
                {
                    v.Update(Buf, ref MaxOffset, ref MaxData);
                }
                Result.AddRange(Buf);
                var SwapBuf = Saver;
                Saver = Buf;
                Buf   = SwapBuf;
                Buf.Clear();
            } while(Saver.Count != 0);
            var id = Result.IndexOf(Result.Last(x => !x.IsLeaf)) + 1;

            Result.RemoveRange(id, Result.Count - id);
            return(Res);
        }
Esempio n. 13
0
        private IBinaryTreeNode <T> AddNodeToSearchTree(IBinaryTreeNode <T> root, IBinaryTreeNode <T> node)
        {
            if (node == null && root == null)
            {
                return(null);
            }
            if (node == null)
            {
                return(root);
            }
            if (root == null || root.Value == null)
            {
                return(node);
            }
            var compareResult = node.Value.CompareTo(root.Value);

            if (compareResult == 0)
            {
                return(root);
            }
            node.Parent = root;
            if (compareResult < 0)
            {
                node.Type = BinaryTreeNodeType.Left;
                root.Left = AddNodeToSearchTree(root.Left, node);
            }
            else
            {
                node.Type  = BinaryTreeNodeType.Right;
                root.Right = AddNodeToSearchTree(root.Right, node);
            }
            return(root);
        }
Esempio n. 14
0
 /// <summary>
 /// Gets/Sets the value for a key
 /// </summary>
 /// <param name="key">Key</param>
 /// <returns>Returns the value associated with the key</returns>
 /// <exception cref="KeyNotFoundException">Thrown if the key doesn't exist</exception>
 public TValue this[TKey key]
 {
     get
     {
         IBinaryTreeNode <TKey, TValue> n = this.Find(key);
         if (n != null)
         {
             return(n.Value);
         }
         throw new KeyNotFoundException();
     }
     set
     {
         bool created = false;
         IBinaryTreeNode <TKey, TValue> n = this.MoveToNode(key, out created);
         if (n != null)
         {
             n.Value = value;
         }
         else
         {
             throw new KeyNotFoundException();
         }
     }
 }
        protected IBinaryTreeNode <ValueType> Balance(IBinaryTreeNode <ValueType> node)
        {
            int bf = GetBalanceFactor(node);

            if (bf >= 2)
            {
                int bfL = GetBalanceFactor(node.leftChild);
                if (bfL >= 0)
                {
                    return(RotateLL(node));
                }
                else
                {
                    return(RotateLR(node));
                }
            }
            else if (bf <= -2)
            {
                int bfR = GetBalanceFactor(node.rightChild);
                if (bfR <= 0)
                {
                    return(RotateRR(node));
                }
                else
                {
                    return(RotateRL(node));
                }
            }
            else
            {
                return(node);
            }
        }
Esempio n. 16
0
        public IBinaryTree <T> BuildTree(List <T> nodeValues, BinaryTreeType type)
        {
            if (nodeValues == null || nodeValues.Count == 0)
            {
                return(null);
            }
            var nodes = new List <IBinaryTreeNode <T> >();
            var depth = 0;

            foreach (var value in nodeValues)
            {
                nodes.Add(_nodeProvider.GetBinaryTreeNode(value));
            }
            IBinaryTreeNode <T> root = null;

            switch (type)
            {
            case BinaryTreeType.Complete:
            {
                root = BuildCompleteTree(nodes);
                break;
            }

            case BinaryTreeType.Search:
            {
                root = BuildSearchTree(nodes);
                break;
            }
            }
            root.Type = BinaryTreeNodeType.Root;
            GetDepth(root, ref depth);
            return(new BinaryTree <T>(root, nodes.Count, depth, type));
        }
Esempio n. 17
0
 /// <summary>
 /// Creates a new Binary Tree Node
 /// </summary>
 /// <param name="parent">Parent</param>
 /// <param name="key">Key</param>
 /// <param name="value">Value</param>
 public BinaryTreeNode(IBinaryTreeNode <TKey, TValue> parent, TKey key, TValue value)
 {
     this.Parent = parent;
     this.Key    = key;
     this.Value  = value;
     this.Size   = 1;
 }
Esempio n. 18
0
 public void Remove(IBinaryTreeNode <TItem> node, IBinaryTreeNode <TItem> parent)
 {
     if (node.Item.CompareTo(Item) < 0)
     {
         LeftNode?.Remove(node, this);
     }
     else if (node.Item.CompareTo(Item) > 0)
     {
         RightNode?.Remove(node, this);
     }
     else
     {
         if (LeftNode != null && RightNode != null)
         {
             parent.RightNode = MinItem;
         }
         else if (parent.LeftNode == this)
         {
             parent.LeftNode = LeftNode ?? RightNode;
         }
         else if (parent.RightNode == this)
         {
             parent.RightNode = LeftNode ?? RightNode;
         }
     }
 }
Esempio n. 19
0
 public void Add(IBinaryTreeNode <TItem> node)
 {
     if (Item.CompareTo(node.Item) > 0)
     {
         if (LeftNode == null)
         {
             LeftNode = node;
         }
         else
         {
             LeftNode.Add(node);
         }
     }
     else if (Item.CompareTo(node.Item) < 0)
     {
         if (RightNode == null)
         {
             RightNode = node;
         }
         else
         {
             RightNode.Add(node);
         }
     }
 }
Esempio n. 20
0
 /// <summary>
 /// Rebalances a right subtree
 /// </summary>
 /// <param name="nodes">Nodes</param>
 /// <param name="start">Range start</param>
 /// <param name="end">Range end</param>
 /// <returns></returns>
 private IBinaryTreeNode <TKey, TValue> RebalanceRightSubtree(IBinaryTreeNode <TKey, TValue>[] nodes, int start, int end)
 {
     if (start > end)
     {
         return(null);
     }
     if (end == start)
     {
         return(nodes[start]);
     }
     if (end - start == 1)
     {
         IBinaryTreeNode <TKey, TValue> root = nodes[start];
         root.RightChild = nodes[end];
         return(root);
     }
     else if (end - start == 2)
     {
         IBinaryTreeNode <TKey, TValue> root = nodes[start + 1];
         root.LeftChild  = nodes[start];
         root.RightChild = nodes[end];
         return(root);
     }
     else
     {
         //Rebuild the tree
         int median = start + ((end - start) / 2);
         //Console.WriteLine("m = " + median);
         IBinaryTreeNode <TKey, TValue> root = nodes[median];
         root.LeftChild  = this.RebalanceLeftSubtree(nodes, start, median - 1);
         root.RightChild = this.RebalanceRightSubtree(nodes, median + 1, end);
         return(root);
     }
 }
Esempio n. 21
0
        private static IEnumerable <Tuple <IBinaryTreeNode, TLevel> > LevelOrderTraverse <TLevel>(
            IBinaryTreeNode partialroot,
            TLevel seed,
            Func <TLevel, IBinaryTreeNode, TLevel> leftlevelfunc,
            Func <TLevel, IBinaryTreeNode, TLevel> rightlevelfunc)
        {
            var queue = new Queue <Tuple <IBinaryTreeNode, TLevel> >();

            queue.Enqueue(new Tuple <IBinaryTreeNode, TLevel>(partialroot, seed));
            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                if (!SentinelEx.EqualNull(current.Item1.LeftChild))
                {
                    queue.Enqueue(new Tuple <IBinaryTreeNode, TLevel>(current.Item1.LeftChild,
                                                                      leftlevelfunc == null ? current.Item2 : leftlevelfunc(current.Item2, partialroot)));
                }
                if (!SentinelEx.EqualNull(current.Item1.RightChild))
                {
                    queue.Enqueue(new Tuple <IBinaryTreeNode, TLevel>(current.Item1.RightChild,
                                                                      rightlevelfunc == null ? current.Item2 : rightlevelfunc(current.Item2, partialroot)));
                }
                yield return(current);
            }
        }
Esempio n. 22
0
        public bool TryGetKey(TKey key, out TKey actualKey)
        {
            ITree <IBinaryTreeNode <TKey, TValue>, TKey, TValue> tree;
            int hash = this._hashFunc(key);

            if (this._dict.TryGetValue(hash, out tree))
            {
                IBinaryTreeNode <TKey, TValue> node = tree.Find(key);
                if (node == null)
                {
                    actualKey = default(TKey);
                    return(false);
                }
                else
                {
                    actualKey = node.Key;
                    return(true);
                }
            }
            else
            {
                actualKey = default(TKey);
                return(false);
            }
        }
Esempio n. 23
0
        public static int GetDegree(this IBinaryTreeNode node)
        {
            Contract.Requires <ArgumentNullException>(node != null);
            Contract.Ensures(Contract.Result <int>() >= 0 && Contract.Result <int>() <= 2);

            if (SentinelEx.NotEqualNull(node.LeftChild))
            {
                if (SentinelEx.NotEqualNull(node.RightChild))
                {
                    return(2);
                }
                else
                {
                    return(1);
                }
            }
            else if (SentinelEx.NotEqualNull(node.RightChild))
            {
                return(1);
            }
            else
            {
                return(0);
            }
        }
Esempio n. 24
0
        /// <summary>
        /// Finds a Node based on the key
        /// </summary>
        /// <param name="key">Key</param>
        /// <returns>Node associated with the given Key or null if the key is not present in the tree</returns>
        public virtual IBinaryTreeNode <TKey, TValue> Find(TKey key)
        {
            if (this.Root == null)
            {
                return(null);
            }

            //Iteratively binary search for the key
            IBinaryTreeNode <TKey, TValue> current = this.Root;

            do
            {
                int c = this._comparer.Compare(key, current.Key);
                if (c < 0)
                {
                    current = current.LeftChild;
                }
                else if (c > 0)
                {
                    current = current.RightChild;
                }
                else
                {
                    //If we find a match on the key then return it
                    return(current);
                }
            } while (current != null);

            return(null);
        }
Esempio n. 25
0
        public static IEnumerable <IBinaryTreeNode> TraverseSubtree(this IBinaryTreeNode partialroot, TraverseOrder order = TraverseOrder.InOrder)
        {
            Contract.Requires <ArgumentNullException>(partialroot != null);
            Contract.Ensures(Contract.Result <IEnumerable <IBinaryTreeNode> >() != null);

            return(partialroot.TraverseSubtree <object>(null, null, null, order).Select(res => res.Item1));
        }
Esempio n. 26
0
        private IEnumerable <T> InternalPreorder(IBinaryTreeNode <T> node)
        {
            var list  = new List <T>();
            var stack = new Stack <IBinaryTreeNode <T> >();

            stack.Push(node);

            while (stack.Count > 0)
            {
                var cur = stack.Pop();
                list.Add(cur.Data);

                if (cur.Right != null)
                {
                    stack.Push(cur.Right);
                }

                if (cur.Left != null)
                {
                    stack.Push(cur.Left);
                }
            }

            return(list);
        }
Esempio n. 27
0
        public static void BreadthFirstSearch <T>(IBinaryTreeNode <T> node, Action <int, T> output) where T : IBinaryTreeNode <T>
        {
            Queue <IBinaryTreeNode <T> > next = new Queue <IBinaryTreeNode <T> >();

            next.Enqueue(node);

            int level = 0;

            do
            {
                Queue <IBinaryTreeNode <T> > current = next;

                next = new Queue <IBinaryTreeNode <T> >();

                while (current.TryDequeue(out IBinaryTreeNode <T> item))
                {
                    output(level, item.Value);

                    if (item.Left != null)
                    {
                        next.Enqueue(item.Left);
                    }

                    if (item.Right != null)
                    {
                        next.Enqueue(item.Right);
                    }
                }
            } while (next.Count > 0);
        }
Esempio n. 28
0
		/// <summary>
		/// Finds the two values nearest to the search value, one above and one below.
		/// If an exact match is found, that value is returned in both tuple positions.
		/// </summary>
		/// <param name="searchFor">The search for.</param>
		/// <returns></returns>
		/// <remarks></remarks>
		public Tuple<TValue, TValue> FindNearestValues(TValue searchFor)
		{
			TValue left = default(TValue);
			TValue right = default(TValue);
			IBinaryTreeNode<TNode, TValue> currentNode = _root;
			while (true)
			{
				int compareResult = searchFor.CompareTo(currentNode.Value);
				if (compareResult == 0)
				{
					return new Tuple<TValue, TValue>(currentNode.Value, currentNode.Value);
				}
				if (compareResult < 0)
				{
					right = currentNode.Value;
					if (currentNode.Left == null)
					{
						return new Tuple<TValue, TValue>(left, right);
					}
					currentNode = currentNode.Left;
				}
				else
				{
					left = currentNode.Value;
					if (currentNode.Right == null)
					{
						return new Tuple<TValue, TValue>(left, right);
					}
					currentNode = currentNode.Right;
				}
			}
		}
Esempio n. 29
0
        /// <summary>
        /// Tries to move to a node based on its index
        /// </summary>
        /// <param name="index">Index</param>
        /// <returns>Node</returns>
        /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of range</exception>
        protected IBinaryTreeNode <TKey, TValue> MoveToIndex(int index)
        {
            if (this.Root == null)
            {
                throw new IndexOutOfRangeException();
            }
            int count = this.Root.Size;

            if (index < 0 || index >= count)
            {
                throw new IndexOutOfRangeException();
            }

            // Special cases
            // Index 0 and only one node, return the root
            if (index == 0 && count == 1)
            {
                return(this.Root);
            }
            // Index 0, return the left most child
            if (index == 0)
            {
                return(this.Root.FindLeftmostChild());
            }
            // Index == count - 1, return the right most child
            if (index == count - 1)
            {
                return(this.Root.FindRightmostChild());
            }

            long baseIndex = 0;
            IBinaryTreeNode <TKey, TValue> currentNode = this.Root;

            while (true)
            {
                long currentIndex = currentNode.LeftChild != null ? baseIndex + currentNode.LeftChild.Size : baseIndex;
                if (currentIndex == index)
                {
                    return(currentNode);
                }

                if (currentIndex > index)
                {
                    // We're at a node where our calculated index is greater than the desired so need to move to the left sub-tree
                    currentNode = currentNode.LeftChild;
                    continue;
                }

                // We're at a node where our calculated index is less than the desired so need to move to the right sub-tree
                // Plus we need to adjust the base appropriately
                if (currentNode.RightChild != null)
                {
                    currentNode = currentNode.RightChild;
                    baseIndex   = currentIndex + 1;
                    continue;
                }
                throw new InvalidOperationException();
            }
        }
        public IBinaryTreeNode <TResult> Visit(BinaryTreeNode <TItem> node)
        {
            TResult mappedItem = selector(node.Item);
            IBinaryTreeNode <TResult> mappedLeft  = node.Left.Accept(this);
            IBinaryTreeNode <TResult> mappedRight = node.Right.Accept(this);

            return(BinaryTree.Node(mappedItem, mappedLeft, mappedRight));
        }
Esempio n. 31
0
 /// <summary>
 /// Creates a new instance of a tree node.
 /// </summary>
 /// <param name="parent">The parent of the node to create.</param>
 public BinaryTreeNode(IBinaryTreeNode parent)
     : this(parent, null)
 {
 }
Esempio n. 32
0
 /// <summary>
 /// Clears the binary tree of all of its items.
 /// </summary>
 public virtual void Clear()
 {
     _root = null;
 }
Esempio n. 33
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 public BinaryTree()
 {
     _root = null;
 }
 private static int NodeHeight(IBinaryTreeNode<int, int> tree)
 {
     if (tree == null) return 0;
     return Math.Max(NodeHeight(tree.Left), NodeHeight(tree.Right)) + 1;
 }
Esempio n. 35
0
        protected virtual string PreorderTraversal(IBinaryTreeNode current, string separator)
        {
            if (current != null)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(current.Value.ToString());
                sb.Append(separator);

                sb.Append(PreorderTraversal(current.LeftChild, separator));
                sb.Append(PreorderTraversal(current.RightChild, separator));
                return sb.ToString();
            }
            else
                return String.Empty;
        }
Esempio n. 36
0
 /// <summary>
 /// Creates a new instance of a tree node.
 /// </summary>
 /// <param name="parent">The parent of the node to create.</param>
 /// <param name="Value">The value stored at the tree node.</param>
 public BinaryTreeNode(IBinaryTreeNode parent, object Value)
     : base(parent, Value, new TreeNodes(2))
 {
 }
Esempio n. 37
0
 /// <summary>
 /// Builds an arraylist of the inorder traversal of the tree.
 /// </summary>
 /// <param name="current">The current binary tree node.</param>
 /// <param name="contents">The contents of the tree.</param>
 protected virtual void InorderTraversalBuildup(IBinaryTreeNode current, System.Collections.ArrayList contents)
 {
     if (current != null)
     {
         InorderTraversalBuildup(current.LeftChild, contents);
         contents.Add(current);
         InorderTraversalBuildup(current.RightChild, contents);
     }
 }
Esempio n. 38
0
 /// <summary>
 /// Search helper method that assists in locating the current binary node for the specified data item.
 /// </summary>
 /// <param name="current">The current node to begin the search with.</param>
 /// <param name="data">The data to look for.</param>
 /// <returns>A reference to the node that the data is contained in.</returns>
 protected virtual IBinaryTreeNode SearchHelper(IBinaryTreeNode current, IComparable data)
 {
     if (current == null)
         return null;	// node was not found
     else
     {
         // get the comparable instance from the value of the object.
         IComparable currval = current.Value as IComparable;
         // if the current value is not comparable return null stating that we can not locate the node.
         if (currval == null) return null;
         // get the compare to results
         int result = currval.CompareTo(data);
         if (result == 0)
             // they are equal - we found the data
             return current;
         else if (result > 0)
         {
             // current.Value > n.Value
             // therefore, if the data exists it is in current's left subtree
             return SearchHelper(current.LeftChild, data);
         }
         else // result < 0
         {
             // current.Value < n.Value
             // therefore, if the data exists it is in current's right subtree
             return SearchHelper(current.RightChild, data);
         }
     }
 }