Beispiel #1
0
        /// <summary>
        /// Checks various properties to determine if the tree is a valid AA Tree.
        /// Throws exceptions if properties are violated.
        /// Useful for debugging.
        /// </summary>
        /// <remarks>
        /// The properties that are checked are:
        /// <list type="number">
        /// <item>The level of every leaf node is one.</item>
        /// <item>The level of every left child is exactly one less than that of its parent.</item>
        /// <item>The level of every right child is equal to or one less than that of its parent.</item>
        /// <item>The level of every right grandchild is strictly less than that of its grandparent.</item>
        /// <item>Every node of level greater than one has two children.</item>
        /// </list>
        /// More information: https://en.wikipedia.org/wiki/AA_tree .
        /// </remarks>
        /// <param name="node">The node to check from.</param>
        /// <returns>true if node passes all checks, false otherwise.</returns>
        private static bool Validate <T>(AATreeNode <T>?node)
        {
            if (node == null)
            {
                return(true);
            }

            // Check level == 1 if node if a leaf node.
            var leafNodeCheck = CheckLeafNode(node);

            // Check level of left child is exactly one less than parent.
            var leftCheck = CheckLeftSubtree(node);

            // Check level of right child is equal or one less than parent.
            var rightCheck = CheckRightSubtree(node);

            // Check right grandchild level is less than node.
            var grandchildCheck = CheckRightGrandChild(node);

            // Check if node has two children if not leaf.
            var nonLeafChildrenCheck = CheckNonLeafChildren(node);

            var thisNodeResult = leafNodeCheck && leftCheck && rightCheck;

            thisNodeResult = thisNodeResult && grandchildCheck && nonLeafChildrenCheck;

            return(thisNodeResult && Validate(node.Left) && Validate(node.Right));
        }
Beispiel #2
0
        // Tree Balancing After Adding an item
        private void BalanceTreeAfterAdd(Stack <AATreeNode> parentNodes)
        {
            AATreeNode parentNode = null;

            while (parentNodes.Count > 0)
            {
                var node = parentNodes.Pop();
                if (parentNodes.Count > 0)
                {
                    parentNode = parentNodes.Peek();
                }
                else
                {
                    parentNode = null;
                }

                // maintain two properties
                // 1. if a node and its left child have same level then rotate right.
                // 2. if a node, its right child and right node's right child have same level then rotate left.
                if (parentNode != null)
                {
                    bool isLeftNode = parentNode.Left == node;
                    RotateRight(parentNode, isLeftNode ? parentNode.Left : parentNode.Right);
                    RotateLeft(parentNode, isLeftNode ? parentNode.Left : parentNode.Right);
                }
                else
                {
                    // check root node.
                    RotateRight(null, this.root);
                    RotateLeft(null, this.root);
                }
            }
        }
Beispiel #3
0
        // PreOrder Traversal implementation.
        private static IEnumerable <T> PreOrderTraversal(AATreeNode node)
        {
            if (node == AATree <T> .NullNode)
            {
                yield break;
            }

            Stack <AATreeNode> stack = new Stack <AATreeNode>();

            stack.Push(node);
            AATreeNode currentNode = AATree <T> .NullNode;

            while (stack.Count > 0)
            {
                currentNode = stack.Pop();
                if (currentNode.Right != AATree <T> .NullNode)
                {
                    stack.Push(currentNode.Right);
                }

                if (currentNode.Left != AATree <T> .NullNode)
                {
                    stack.Push(currentNode.Left);
                }

                yield return(currentNode.Value);
            }
        }
Beispiel #4
0
        // InOrder Traversal implementation.
        private static IEnumerable <T> InOrderTraversal(AATreeNode node)
        {
            if (node == AATree <T> .NullNode)
            {
                yield break;
            }

            Stack <AATreeNode> nodes       = new Stack <AATreeNode>();
            AATreeNode         currentNode = node;

            while (nodes.Count > 0 || currentNode != AATree <T> .NullNode)
            {
                if (currentNode != AATree <T> .NullNode)
                {
                    nodes.Push(currentNode);
                    currentNode = currentNode.Left;
                }
                else
                {
                    currentNode = nodes.Pop();
                    yield return(currentNode.Value);

                    currentNode = currentNode.Right;
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Searches for the specified value in the AATree.
        /// If found returns the node containing the value in node out param, else this param contains NullNode.
        /// </summary>
        /// <param name="value">Value to search.</param>
        /// <param name="node">AATree node.</param>
        /// <returns>Returns true if the value is found, else returns false.</returns>
        internal bool TrySearch(T value, out AATreeNode node)
        {
            bool result = false;

            node = AATree <T> .NullNode;

            var currentNode = this.root;

            while (currentNode != AATree <T> .NullNode)
            {
                int compResult = this.Comparer.Compare(value, currentNode.Value);
                if (compResult == 0)
                {
                    node   = currentNode;
                    result = true;
                    break;
                }

                if (compResult < 0)
                {
                    //goto left
                    currentNode = currentNode.Left;
                }
                else
                {
                    //goto right
                    currentNode = currentNode.Right;
                }
            }

            return(result);
        }
Beispiel #6
0
 public AATreeNode(T value, AATreeNode nullNode)
 {
     this.Value = value;
     this.Left  = nullNode;
     this.Right = nullNode;
     this.Level = 1;
 }
Beispiel #7
0
        // Tree Balancing After remving an item
        private void BalanceTreeAfterRemove(Stack <AATreeNode> parentNodes)
        {
            AATreeNode parentNode = null;

            // balance the tree.
            while (parentNodes.Count > 0)
            {
                var node = parentNodes.Pop();
                if ((node.Level - node.Left.Level) > 1 || (node.Level - node.Right.Level) > 1)
                {
                    node.Level--;
                    if (node.Right.Level > node.Level)
                    {
                        node.Right.Level = node.Level;
                    }

                    if (parentNodes.Count > 0)
                    {
                        parentNode = parentNodes.Peek();
                    }
                    else
                    {
                        parentNode = null;
                    }

                    if (parentNode != null)
                    {
                        bool isLeftNode = parentNode.Left == node;

                        if (RotateRight(parentNode, node))
                        {
                            // get the new child from parent.
                            node = isLeftNode ? parentNode.Left : parentNode.Right;
                        }

                        if (RotateRight(node, node.Right))
                        {
                            if (RotateRight(node.Right, node.Right.Right))
                            {
                                if (RotateLeft(parentNode, node))
                                {
                                    node = isLeftNode ? parentNode.Left : parentNode.Right;
                                }
                            }
                        }

                        RotateLeft(node, node.Right);
                    }
                    else
                    {
                        RotateRight(null, this.root);
                        RotateRight(this.root, this.root.Right);
                        RotateRight(this.root.Right, this.root.Right.Right);
                        RotateLeft(null, this.root);
                        RotateLeft(this.root, this.root.Right);
                    }
                }
            }
        }
        /// <summary>
        /// Checks if right grandchild's (right node's right node) level is less than node.
        /// </summary>
        /// <param name="node">The node to check.</param>
        /// <returns>true if node passes check, false otherwise.</returns>
        private bool CheckRightGrandChild <T>(AATreeNode <T> node)
        {
            var condition = node.Right != null &&
                            node.Right.Right != null &&
                            node.Right.Level < node.Right.Right.Level;

            return(!condition);
        }
Beispiel #9
0
        /// <summary>
        /// Checks if right node's level is either equal to or one less than node's level.
        /// </summary>
        /// <param name="node">The node to check.</param>
        /// <returns>true if node passes check, false otherwise.</returns>
        private static bool CheckRightSubtree <T>(AATreeNode <T> node)
        {
            var condition = node.Right != null &&
                            node.Level - node.Right.Level != 1 &&
                            node.Level != node.Right.Level;

            return(!condition);
        }
Beispiel #10
0
        // PostOrder Traversal implementation.
        private static IEnumerable <T> PostOrderTraversal(AATreeNode node)
        {
            if (node == AATree <T> .NullNode)
            {
                yield break;
            }

            Stack <AATreeNode> nodes       = new Stack <AATreeNode>();
            AATreeNode         currentNode = node;

            while (true)
            {
                if (currentNode != AATree <T> .NullNode)
                {
                    if (currentNode.Right != AATree <T> .NullNode)
                    {
                        nodes.Push(currentNode.Right);
                    }

                    nodes.Push(currentNode);
                    currentNode = currentNode.Left;
                }
                else
                {
                    if (nodes.Count == 0)
                    {
                        break;
                    }

                    currentNode = nodes.Pop();
                    if (currentNode.Right != AATree <T> .NullNode && nodes.Count > 0 && nodes.Peek() == currentNode.Right)
                    {
                        nodes.Pop();             // remove right;
                        nodes.Push(currentNode); // push current
                        currentNode = currentNode.Right;
                    }
                    else
                    {
                        yield return(currentNode.Value);

                        currentNode = AATree <T> .NullNode;
                    }
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Split or Rotate left.
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        private bool RotateLeft(AATreeNode parentNode, AATreeNode node)
        {
            bool result = false;

            if (node == AATree <T> .NullNode)
            {
                return(result);
            }

            if (node.Level == node.Right.Level && node.Right.Level == node.Right.Right.Level)
            {
                // rotate left.
                var nodeToMoveUp = node.Right;
                node.Right        = nodeToMoveUp.Left;
                nodeToMoveUp.Left = node;
                if (parentNode != null)
                {
                    if (parentNode.Left == node)
                    {
                        parentNode.Left = nodeToMoveUp;
                        parentNode.Left.Level++;
                    }
                    else
                    {
                        parentNode.Right = nodeToMoveUp;
                        parentNode.Right.Level++;
                    }
                }
                else
                {
                    this.root = nodeToMoveUp;
                    this.root.Level++;
                }

                result = true;
            }

            return(result);
        }
Beispiel #12
0
        /// <summary>
        /// Checks if node is a leaf, and if so if its level is 1.
        /// </summary>
        /// <param name="node">The node to check.</param>
        /// <returns>true if node passes check, false otherwise.</returns>
        private static bool CheckLeafNode <T>(AATreeNode <T> node)
        {
            var condition = node.Left == null && node.Right == null && node.Level != 1;

            return(!condition);
        }
        /// <summary>
        /// Checks if left node's level is exactly one less than node's level.
        /// </summary>
        /// <param name="node">The node to check.</param>
        /// <returns>true if node passes check, false otherwise.</returns>
        private bool CheckLeftSubtree <T>(AATreeNode <T> node)
        {
            var condition = node.Left != null && node.Level - node.Left.Level != 1;

            return(!condition);
        }
Beispiel #14
0
 /// <summary>
 /// Initializes an instance of AATree class with specified comparer.
 /// </summary>
 /// <param name="comparer">Comparer to compare values.</param>
 public AATree(IComparer <T> comparer)
 {
     this.Comparer     = comparer;
     this.root         = AATree <T> .NullNode;
     this.DefaultValue = default(T);
 }
Beispiel #15
0
        /// <summary>
        /// Tries to remove specified value from the AATree.
        /// </summary>
        /// <param name="value">Value to remove.</param>
        /// <returns>Returns true if the value is found and removed successfully, else returns false.</returns>
        public bool Remove(T value)
        {
            // Step1. Serach for the value in the tree
            // Step2. if not found return false, if found then go to step3.
            // Step3. if the node is a leaf node then delete the node, else if the node has only one child then delete
            //        the node and assign its child to parent,
            //        else if the node has two child then find a node which can be replaced by the node to be deleted
            //        (use LeftmostRight or RightmostLeft node)
            //Step4. balance the tree.

            bool result = false;
            Stack <AATreeNode> parentNodes = new Stack <AATreeNode>();
            AATreeNode         node        = this.root;

            while (node != AATree <T> .NullNode)
            {
                int keyCompResult = this.Comparer.Compare(value, node.Value);
                if (keyCompResult == 0)
                {
                    result = true;
                    break;
                }
                else if (keyCompResult < 0)
                {
                    //if key is lessthan the node.Key goto left
                    parentNodes.Push(node);
                    node = node.Left;
                }
                else
                {
                    //if key is greaterthan the node.Key goto right
                    parentNodes.Push(node);
                    node = node.Right;
                }
            }

            if (!result)
            {
                return(result);
            }

            AATreeNode nodeToDelete = node;

            if (nodeToDelete.Left != AATree <T> .NullNode && nodeToDelete.Right != AATree <T> .NullNode)
            {
                parentNodes.Push(node);
                // using right most of left sub tree.
                node = nodeToDelete.Left;
                while (node.Right != AATree <T> .NullNode)
                {
                    parentNodes.Push(node);
                    node = node.Right;
                }

                var tval = nodeToDelete.Value;
                nodeToDelete.Value = node.Value;
                node.Value         = tval;
                nodeToDelete       = node;
            }

            AATreeNode parentNode = null;

            if (nodeToDelete.Left == AATree <T> .NullNode || nodeToDelete.Right == AATree <T> .NullNode)
            {
                AATreeNode childNode = nodeToDelete.Left == AATree <T> .NullNode ? nodeToDelete.Right : nodeToDelete.Left;

                if (parentNodes.Count > 0)
                {
                    parentNode = parentNodes.Peek();
                }

                if (parentNode != null)
                {
                    if (parentNode.Left == nodeToDelete)
                    {
                        parentNode.Left = childNode;
                    }
                    else
                    {
                        parentNode.Right = childNode;
                    }
                }
                else
                {
                    this.root = childNode;
                }
            }

            BalanceTreeAfterRemove(parentNodes);

            if (result)
            {
                this.Count--;
            }

            return(result);
        }
Beispiel #16
0
        /// <summary>
        /// Checks if node is not a leaf, and if so if it has two children.
        /// </summary>
        /// <param name="node">The node to check.</param>
        /// <returns>true if node passes check, false otherwise.</returns>
        private static bool CheckNonLeafChildren <T>(AATreeNode <T> node)
        {
            var condition = node.Level > 1 && (node.Left == null || node.Right == null);

            return(!condition);
        }
Beispiel #17
0
        /// <summary>
        /// Tries to add specified value to the AATree.
        /// If the value is already present in the tree then this method returns without adding.
        /// </summary>
        /// <param name="value">Value to add.</param>
        /// <returns>Returns true if value is added successfully, else returns false.</returns>
        public bool Add(T value)
        {
            bool result = false;

            if (this.root == AATree <T> .NullNode)
            {
                this.root = new AATreeNode(value, AATree <T> .NullNode);
                result    = true;
            }

            if (!result)
            {
                AATreeNode         node        = this.root;
                Stack <AATreeNode> parentNodes = new Stack <AATreeNode>();
                while (true)
                {
                    int keyCompResult = Comparer.Compare(value, node.Value);
                    if (keyCompResult == 0)
                    {
                        // key already exists.
                        result = false;
                        break;
                    }
                    else if (keyCompResult < 0)
                    {
                        // go to left.
                        if (node.Left == AATree <T> .NullNode)
                        {
                            node.Left = new AATreeNode(value, AATree <T> .NullNode);

                            result = true;
                            break;
                        }
                        else
                        {
                            parentNodes.Push(node);
                            node = node.Left;
                        }
                    }
                    else
                    {
                        // go to right.
                        if (node.Right == AATree <T> .NullNode)
                        {
                            node.Right = new AATreeNode(value, AATree <T> .NullNode);
                            result     = true;
                            break;
                        }
                        else
                        {
                            parentNodes.Push(node);
                            node = node.Right;
                        }
                    }
                }

                if (result)
                {
                    parentNodes.Push(node);
                    BalanceTreeAfterAdd(parentNodes);
                }
            }

            if (result)
            {
                Count++;
            }

            return(result);
        }