コード例 #1
0
        //O(N)
        private List <T> InOrderTraverseFullInfo(AVLTreeNodeCPC <T> node)
        {
            var result = new List <T>();

            if (node.leftChild != null)
            {
                result.AddRange(InOrderTraverseFullInfo(node.leftChild));
            }
            result.Add(node.data);
            Console.WriteLine("Node: {0}, Weight: {7}, Parent: {1}, LeftChild: {2}, RightChild: {3}, LeftHeight: {4}, RightHeight: {5}, ChildrenNum: {6}",
                              node.data.ToString(),
                              node.parent == null ? "null" : node.parent.data.ToString(),
                              node.leftChild == null ? "null" : node.leftChild.data.ToString(),
                              node.rightChild == null ? "null" : node.rightChild.data.ToString(),
                              node.leftHeight,
                              node.rightHeight,
                              node.childrenNum,
                              node.weight);
            if (node.rightChild != null)
            {
                result.AddRange(InOrderTraverseFullInfo(node.rightChild));
            }

            return(result);
        }
コード例 #2
0
 private void Rotate(AVLTreeNodeCPC <T> parent, bool isChildLeft, bool isGrandchildLeft)
 {
     try
     {
         if (isChildLeft && isGrandchildLeft)
         {
             RightRotate(parent);
         }
         else if (isChildLeft && !isGrandchildLeft)
         {
             LeftRightRotate(parent);
         }
         else if (!isChildLeft && isGrandchildLeft)
         {
             RightLeftRotate(parent);
         }
         else if (!isChildLeft && !isGrandchildLeft)
         {
             LeftRotate(parent);
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.ToString());
     }
 }
コード例 #3
0
        private void MinusParentChildrenNum(AVLTreeNodeCPC <T> node)
        {
            var parent = node.parent;

            while (parent != null)
            {
                parent.childrenNum--;
                parent = parent.parent;
            }
        }
コード例 #4
0
 private void UpdateChildrenNumberByDirectChildren(AVLTreeNodeCPC <T> parent)
 {
     parent.childrenNum = 0;
     if (parent.leftChild != null)
     {
         parent.childrenNum += parent.leftChild.childrenNum + parent.leftChild.weight;
     }
     if (parent.rightChild != null)
     {
         parent.childrenNum += parent.rightChild.childrenNum + parent.rightChild.weight;
     }
 }
コード例 #5
0
        //O(N)
        private List <T> InOrderTraverse(AVLTreeNodeCPC <T> node)
        {
            var result = new List <T>();

            if (node.leftChild != null)
            {
                result.AddRange(InOrderTraverse(node.leftChild));
            }
            result.Add(node.data);
            if (node.rightChild != null)
            {
                result.AddRange(InOrderTraverse(node.rightChild));
            }

            return(result);
        }
コード例 #6
0
        private void RightRotate(AVLTreeNodeCPC <T> parent)
        {
            //parent must have a left child
            var newParent = parent.leftChild;

            //1. Update each node's parent
            newParent.parent = parent.parent;
            parent.parent    = newParent;
            if (parent.leftChild.rightChild != null)
            {
                parent.leftChild.rightChild.parent = parent;
            }

            //2. Update each node's child
            parent.leftChild     = parent.leftChild.rightChild;
            newParent.rightChild = parent;

            //3. Update height
            if (parent.leftChild != null)
            {
                parent.leftHeight = Math.Max(parent.leftChild.leftHeight, parent.leftChild.rightHeight) + 1;
            }
            else
            {
                parent.leftHeight = 0;
            }
            newParent.rightHeight = Math.Max(parent.leftHeight, parent.rightHeight) + 1;

            //4. Update children number
            UpdateChildrenNumberByDirectChildren(parent);
            UpdateChildrenNumberByDirectChildren(newParent);

            //5. Update new parent's parent
            if (newParent.parent == null)
            {
                root = newParent;
            }
            else if (newParent.parent.leftChild == parent)
            {
                newParent.parent.leftChild = newParent;
            }
            else
            {
                newParent.parent.rightChild = newParent;
            }
        }
コード例 #7
0
        private int CheckChildrenNum(AVLTreeNodeCPC <T> node)
        {
            var currentNode = node;

            while (currentNode != null)
            {
                var left  = CheckChildrenNum(currentNode.leftChild);
                var right = CheckChildrenNum(currentNode.rightChild);
                if (left + right == currentNode.childrenNum)
                {
                    return(currentNode.childrenNum + currentNode.weight);
                }
                else
                {
                    Console.WriteLine("Node {0} has wrong children number", currentNode.data);
                    return(-1);
                }
            }
            return(0);
        }
コード例 #8
0
        private AVLTreeNodeCPC <T> GetNextInOrderNode(AVLTreeNodeCPC <T> node)
        {
            if (node.rightChild != null)
            {
                var currentNode = node.rightChild;
                while (true)
                {
                    if (currentNode.leftChild != null)
                    {
                        currentNode = currentNode.leftChild;
                    }
                    else
                    {
                        return(currentNode);
                    }
                }
            }

            return(null);
        }
コード例 #9
0
        private void MinusParentChildrenNum(AVLTreeNodeCPC <T> node, AVLTreeNodeCPC <T> endNode, int weight)
        {
            var  parent            = node.parent;
            bool hasReachedEndNode = false;

            while (parent != null)
            {
                if (parent == endNode)
                {
                    hasReachedEndNode = true;
                }
                if (hasReachedEndNode)
                {
                    parent.childrenNum--;
                }
                else
                {
                    parent.childrenNum -= weight;
                }
                parent = parent.parent;
            }
        }
コード例 #10
0
 private void RightLeftRotate(AVLTreeNodeCPC <T> parent)
 {
     //parent must have a right child and a right-left grandchild
     RightRotate(parent.rightChild);
     LeftRotate(parent);
 }
コード例 #11
0
 private void LeftRightRotate(AVLTreeNodeCPC <T> parent)
 {
     //parent must have a left child and a left-right grandchild
     LeftRotate(parent.leftChild);
     RightRotate(parent);
 }
コード例 #12
0
        private void BalanceNode(AVLTreeNodeCPC <T> newNode)
        {
            if (newNode == null)
            {
                return;
            }
            var currentNode      = newNode;
            var parent           = newNode;
            var isChildLeft      = true;
            var isGrandchildLeft = true;

            while (parent != null)
            {
                if (parent.leftChild == currentNode)
                {//Left Child
                    parent.leftHeight = Math.Max(currentNode.leftHeight, currentNode.rightHeight) + 1;
                }
                else if (parent.rightChild == currentNode)
                {//Right Child
                    parent.rightHeight = Math.Max(currentNode.leftHeight, currentNode.rightHeight) + 1;
                }
                else
                {//First time
                    if (parent.leftChild != null)
                    {
                        parent.leftHeight = Math.Max(parent.leftChild.leftHeight, parent.leftChild.rightHeight) + 1;
                    }
                    else
                    {
                        parent.leftHeight = 0;
                    }
                    if (parent.rightChild != null)
                    {
                        parent.rightHeight = Math.Max(parent.rightChild.leftHeight, parent.rightChild.rightHeight) + 1;
                    }
                    else
                    {
                        parent.rightHeight = 0;
                    }
                }

                var diff = parent.leftHeight - parent.rightHeight;
                if (diff >= 2 || diff <= -2)
                {
                    if (parent.leftHeight > parent.rightHeight)
                    {
                        isChildLeft = true;
                        //The balance of sub tree may be 0 on a deletion. Do not double-rotate in this case.
                        if (parent.leftChild.leftHeight >= parent.leftChild.rightHeight)
                        {
                            isGrandchildLeft = true;
                        }
                        else
                        {
                            isGrandchildLeft = false;
                        }
                    }
                    else
                    {
                        isChildLeft = false;
                        if (parent.rightChild.leftHeight > parent.rightChild.rightHeight)
                        {
                            isGrandchildLeft = true;
                        }
                        else
                        {
                            isGrandchildLeft = false;
                        }
                    }
                    Rotate(parent, isChildLeft, isGrandchildLeft);
                }

                currentNode = parent;
                parent      = parent.parent;
            }
        }
コード例 #13
0
        private bool RemoveDataFromNode(T data, AVLTreeNodeCPC <T> node, bool isLeft)
        {
            if (!node.subTree.RemoveNode(data))
            {
                //Cannot find the node in subtree
                Console.WriteLine("Unable to find {0} in subtree", data);
                return(false);
            }

            if (node.weight > 1)
            {
                node.weight--;
                MinusParentChildrenNum(node);
                return(true);
            }

            if (node.leftChild == null)
            {
                var parent = node.parent;
                if (node.rightChild != null)
                {
                    node.rightChild.parent = parent;
                }

                if (parent == null)
                {
                    //root node
                    root = node.rightChild;
                }
                else
                {
                    if (isLeft)
                    {
                        parent.leftChild = node.rightChild;
                    }
                    else
                    {
                        parent.rightChild = node.rightChild;
                    }
                }
                MinusParentChildrenNum(node);
                BalanceNode(node.parent);
                node = null;//Memory Leak??
            }
            else if (node.rightChild == null)
            {
                var parent = node.parent;
                if (node.leftChild != null)
                {
                    node.leftChild.parent = parent;
                }

                if (parent == null)
                {
                    //root node
                    root = node.leftChild;
                }
                else
                {
                    if (isLeft)
                    {
                        parent.leftChild = node.leftChild;
                    }
                    else
                    {
                        parent.rightChild = node.leftChild;
                    }
                }
                MinusParentChildrenNum(node);
                BalanceNode(node.parent);
                node = null;
            }
            else
            {
                //Get the next node in InOrderTraverse
                var nextNode = GetNextInOrderNode(node);

                if (nextNode.parent == node)
                {
                    if (node.parent == null)
                    {
                        //root node
                        root            = nextNode;
                        nextNode.parent = null;
                    }
                    else
                    {
                        var parent = node.parent;
                        nextNode.parent = parent;

                        if (isLeft)
                        {
                            parent.leftChild = nextNode;
                        }
                        else
                        {
                            parent.rightChild = nextNode;
                        }
                    }
                    nextNode.leftChild = node.leftChild;
                    if (node.leftChild != null)
                    {
                        node.leftChild.parent = nextNode;
                        nextNode.childrenNum += node.leftChild.childrenNum + node.leftChild.weight;
                    }

                    MinusParentChildrenNum(nextNode);
                    BalanceNode(nextNode);
                    node = null;
                }
                else
                {
                    //Copy the value of nextNode to currentNode, then delete nextNode
                    node.data    = nextNode.data;
                    node.weight  = nextNode.weight;
                    node.subTree = nextNode.subTree;
                    nextNode.parent.leftChild = nextNode.rightChild;
                    if (nextNode.rightChild != null)
                    {
                        nextNode.rightChild.parent = nextNode.parent;
                    }
                    MinusParentChildrenNum(nextNode, node, nextNode.weight);
                    UpdateChildrenNumberByDirectChildren(node);
                    BalanceNode(nextNode.parent);
                    nextNode = null;
                }
            }
            return(true);
        }
コード例 #14
0
        //O(LogN)
        public bool InsertNode(T data)
        {
            try
            {
                var newNode = new AVLTreeNodeCPC <T>()
                {
                    data    = data,
                    subTree = new AVLBST <T>(subComparison)
                };
                newNode.subTree.InsertNode(data);

                if (root == null)
                {
                    root = newNode;
                    return(true);
                }

                var currentNode = root;
                while (true)
                {
                    var compareResult = CompareNode(data, currentNode.data);
                    if (compareResult > 0)
                    {
                        currentNode.childrenNum++;
                        if (currentNode.rightChild == null)
                        {
                            currentNode.rightChild = newNode;
                            newNode.parent         = currentNode;
                            break;
                        }
                        else
                        {
                            currentNode = currentNode.rightChild;
                        }
                    }
                    else if (compareResult < 0)
                    {
                        currentNode.childrenNum++;
                        if (currentNode.leftChild == null)
                        {
                            currentNode.leftChild = newNode;
                            newNode.parent        = currentNode;
                            break;
                        }
                        else
                        {
                            currentNode = currentNode.leftChild;
                        }
                    }
                    else
                    {
                        currentNode.weight++;
                        currentNode.subTree.InsertNode(data);
                        return(true);
                    }
                }
                BalanceNode(newNode);

                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            return(false);
        }