Beispiel #1
0
        public void BalanceFactorForRightHeavyTree()
        {
            // Arrange
            var rightOfRight = new AVLTreeNode <int>();
            var right        = new AVLTreeNode <int>();

            right.Right = rightOfRight;

            var root = new AVLTreeNode <int>();

            root.Right = right;

            root.UpdateHeights();

            // Act & Assert
            Assert.Equal(-2, root.BalanceFactor);
            Assert.True(root.TreeIsRightHeavy);
            Assert.False(root.TreeIsLeftHeavy);

            Assert.True(root.RightChildIsRightHeavy);
            Assert.False(root.RightChildIsLeftHeavy);
            Assert.False(root.LeftChildIsLeftHeavy);
            Assert.False(root.LeftChildIsRightHeavy);
        }
Beispiel #2
0
        public void FindBiggestTest()
        {
            // Arrange
            var parent     = new AVLTreeNode <int>();
            var right      = new AVLTreeNode <int>();
            var left       = new AVLTreeNode <int>();
            var leftOfLeft = new AVLTreeNode <int>();

            left.Left    = leftOfLeft;
            left.Parent  = parent;
            right.Parent = parent;

            parent.Right = right;
            parent.Left  = left;

            // To properly use 'height' info
            parent.UpdateHeights();

            // Act
            var actual = parent.GetBiggestHeightOfChilds(parent);

            // Assert
            Assert.Equal(2, actual);
        }
Beispiel #3
0
 /// <summary>
 /// Determines the balance of a given node
 /// </summary>
 protected virtual int getBalance(AVLTreeNode <T> root)
 {
     //Balance = right child's height - left child's height
     return(this.GetHeight(root.RightChild) - this.GetHeight(root.LeftChild));
 }
Beispiel #4
0
    /// <summary>
    /// Removes a given value from the tree and rebalances the tree if necessary.
    /// </summary>
    public override bool Remove(T value)
    {
        AVLTreeNode <T> valueNode = this.Find(value);

        return(this.Remove(valueNode));
    }
        private static int GetNodeDepthAndCheckBalance(AVLTreeNode<KeyValuePair<int, int>> node, out int count)
        {
            count = 0;
            if (node == null) return 0;
            int l_count;
            int r_count;
            var leftDepth = GetNodeDepthAndCheckBalance(node.LeftChild, out l_count);
            var rightDepth = GetNodeDepthAndCheckBalance(node.RightChild, out r_count);
            count = l_count + r_count + 1;
            Assert.AreEqual(count, node.Size);

            var actualBalance = rightDepth - leftDepth;
            Assert.AreEqual(actualBalance, node.Balance);
            Assert.IsTrue(actualBalance >= -1 && actualBalance <= 1);

            return Math.Max(leftDepth, rightDepth) + 1;
        }
Beispiel #6
0
            public bool Remove(T value)
            {
                AVLTreeNode <T> current;

                current = Find(value); // находим узел с удаляемым значением

                if (current == null)   // узел не найден
                {
                    return(false);
                }

                AVLTreeNode <T> treeToBalance = current.Parent; // баланс дерева относительно узла родителя

                Count--;                                        // уменьшение колиества узлов

                // Вариант 1: Если удаляемый узел не имеет правого потомка

                if (current.Right == null)      // если нет правого потомка
                {
                    if (current.Parent == null) // удаляемый узел является корнем
                    {
                        Head = current.Left;    // на место корня перемещаем левого потомка

                        if (Head != null)
                        {
                            Head.Parent = null; // убераем ссылку на родителя
                        }
                    }
                    else // удаляемый узел не является корнем
                    {
                        int result = current.Parent.CompareTo(current.Value);

                        if (result > 0)
                        {
                            // Если значение родительского узла больше значения удаляемого,
                            // сделать левого потомка удаляемого узла, левым потомком родителя.

                            current.Parent.Left = current.Left;
                        }
                        else if (result < 0)
                        {
                            // Если значение родительского узла меньше чем удаляемого,
                            // сделать левого потомка удаляемого узла - правым потомком родительского узла.

                            current.Parent.Right = current.Left;
                        }
                    }
                }

                // Вариант 2: Если правый потомок удаляемого узла не имеет левого потомка, тогда правый потомок удаляемого узла
                // становится потомком родительского узла.

                else if (current.Right.Left == null) // если у правого потомка нет левого потомка
                {
                    current.Right.Left = current.Left;

                    if (current.Parent == null) // текущий элемент является корнем
                    {
                        Head = current.Right;

                        if (Head != null)
                        {
                            Head.Parent = null;
                        }
                    }
                    else
                    {
                        int result = current.Parent.CompareTo(current.Value);
                        if (result > 0)
                        {
                            // Если значение узла родителя больше чем значение удаляемого узла,
                            // сделать правого потомка удаляемого узла, левым потомком его родителя.

                            current.Parent.Left = current.Right;
                        }

                        else if (result < 0)
                        {
                            // Если значение родительского узла меньше значения удаляемого,
                            // сделать правого потомка удаляемого узла - правым потомком родителя.

                            current.Parent.Right = current.Right;
                        }
                    }
                }

                // Вариант 3: Если правый потомок удаляемого узла имеет левого потомка,
                // заместить удаляемый узел, крайним левым потомком правого потомка.
                else
                {
                    // Нахожление крайнего левого узла для правого потомка удаляемого узла.

                    AVLTreeNode <T> leftmost = current.Right.Left;

                    while (leftmost.Left != null)
                    {
                        leftmost = leftmost.Left;
                    }

                    // Родительское правое поддерево становится родительским левым поддеревом.

                    leftmost.Parent.Left = leftmost.Right;

                    // Присвоить крайнему левому узлу, ссылки на правого и левого потомка удаляемого узла.
                    leftmost.Left  = current.Left;
                    leftmost.Right = current.Right;

                    if (current.Parent == null)
                    {
                        Head = leftmost;

                        if (Head != null)
                        {
                            Head.Parent = null;
                        }
                    }
                    else
                    {
                        int result = current.Parent.CompareTo(current.Value);

                        if (result > 0)
                        {
                            // Если значение родительского узла больше значения удаляемого,
                            // сделать крайнего левого потомка левым потомком родителя удаляемого узла.

                            current.Parent.Left = leftmost;
                        }
                        else if (result < 0)
                        {
                            // Если значение родительского узла, меньше чем значение удаляемого,
                            // сделать крайнего левого потомка, правым потомком родителя удаляемого узла.

                            current.Parent.Right = leftmost;
                        }
                    }
                }

                if (treeToBalance != null)
                {
                    treeToBalance.Balance();
                }

                else
                {
                    if (Head != null)
                    {
                        Head.Balance();
                    }
                }

                return(true);
            }
Beispiel #7
0
            AVLTreeNode <TNode> _right;  // правый потомок


            #region Конструктор
            public AVLTreeNode(TNode value, AVLTreeNode <TNode> parent, AVLTree <TNode> tree)
            {
                Value  = value;
                Parent = parent;
                _tree  = tree;
            }
Beispiel #8
0
 private AVLTreeNode <K> RightAndLeftRotate(AVLTreeNode <K> t)
 {
     t.Right = RightRotate(t.Right);
     return(LeftRotate(t));
 }
 public AVLTreeNode(T value, int height, AVLTreeNode <T> parent, AVLTreeNode <T> left, AVLTreeNode <T> right)
 {
     base.Value = value;
     Height     = height;
     Parent     = parent;
     LeftChild  = left;
     RightChild = right;
 }
Beispiel #10
0
        private AVLTreeNode <K> BalanceChild(AVLTreeNode <K> t)
        {
            if (t.Right == null)
            {                    //若右子树删除后为空,则只需判断左子树与根的高度差
                if (Height(t.Left) - t.Height == 2)
                {
                    AVLTreeNode <K> k = t.Left;
                    if (k.Left != null)
                    {
                        t = RightRotate(t);
                    }
                    else
                    {
                        t = LeftAndRightRotate(t);
                    }
                }
            }
            else
            {                          //若右子树删除后非空,则判断左右子树的高度差
                //右子树自身也可能不平衡,故先平衡右子树,再考虑整体
                AVLTreeNode <K> k = t.Right;
                //删除操作默认用右子树上最小节点(靠左)补删除的节点

                if (k.Left != null)
                {
                    if (Height(k.Right) - Height(k.Left) == 2)
                    {
                        AVLTreeNode <K> m = k.Right;
                        if (m.Right != null)
                        {                                //右子树存在,按正常情况单旋转
                            k = LeftRotate(k);
                        }
                        else
                        {                                              //否则是右左情况,双旋转
                            k = RightAndLeftRotate(k);
                        }
                    }
                }
                else
                {
                    if (Height(k.Right) - k.Height == 2)
                    {
                        AVLTreeNode <K> m = k.Right;
                        if (m.Right != null)
                        {                                //右子树存在,按正常情况单旋转
                            k = LeftRotate(k);
                        }
                        else
                        {                                              //否则是右左情况,双旋转
                            k = RightAndLeftRotate(k);
                        }
                    }
                }
                //左子树自身一定是平衡的,左右失衡的话单旋转可以解决问题
                if (Height(t.Left) - Height(t.Right) == 2)
                {
                    t = RightRotate(t);
                }
            }
            return(t);
        }
Beispiel #11
0
        private AVLTreeNode <K> Remove(K x, AVLTreeNode <K> t)
        {
            if (t == null)
            {
                return(null);
            }
            int compareResult = x.CompareTo(t.Key);

            if (compareResult < 0)
            {
                t.Left = Remove(x, t.Left);
                //完了之后验证该子树是否平衡
                if (t.Right != null)
                {                        //若右子树为空,则一定是平衡的,此时左子树相当对父节点深度最多为1, 所以只考虑右子树非空情况
                    if (t.Left == null)
                    {                    //若左子树删除后为空,则需要判断右子树
                        if (Height(t.Right) - t.Height == 2)
                        {
                            AVLTreeNode <K> k = t.Right;
                            if (k.Right != null)
                            {                                    //右子树存在,按正常情况单旋转
                                t = LeftRotate(t);
                            }
                            else
                            {                                                  //否则是右左情况,双旋转
                                t = RightAndLeftRotate(t);
                            }
                        }
                    }
                    if (t.Left != null)
                    {                       //否则判断左右子树的高度差
                        //左子树自身也可能不平衡,故先平衡左子树,再考虑整体
                        AVLTreeNode <K> k = t.Left;
                        //删除操作默认用右子树上最小节点补删除的节点
                        //k的左子树高度不低于k的右子树
                        if (k.Right != null)
                        {
                            if (Height(k.Left) - Height(k.Right) == 2)
                            {
                                AVLTreeNode <K> m = k.Left;
                                if (m.Left != null)
                                {                                     //左子树存在,按正常情况单旋转
                                    k = RightRotate(k);
                                }
                                else
                                {                                                      //否则是左右情况,双旋转
                                    k = LeftAndRightRotate(k);
                                }
                            }
                        }
                        else
                        {
                            if (Height(k.Left) - k.Height == 2)
                            {
                                AVLTreeNode <K> m = k.Left;
                                if (m.Left != null)
                                {                                     //左子树存在,按正常情况单旋转
                                    k = RightRotate(k);
                                }
                                else
                                {                                                      //否则是左右情况,双旋转
                                    k = LeftAndRightRotate(k);
                                }
                            }
                        }
                        if (Height(t.Right) - Height(t.Left) == 2)
                        {
                            //右子树自身一定是平衡的,左右失衡的话单旋转可以解决问题
                            t = LeftRotate(t);
                        }
                    }
                }
                //完了之后更新height值
                t.Height = Math.Max(Height(t.Left), Height(t.Right)) + 1;
            }
            else if (compareResult > 0)
            {
                t.Right = Remove(x, t.Right);
                //下面验证子树是否平衡
                if (t.Left != null)
                {                         //若左子树为空,则一定是平衡的,此时右子树相当对父节点深度最多为1
                    t = BalanceChild(t);
                }
                //完了之后更新height值
                t.Height = Math.Max(Height(t.Left), Height(t.Right)) + 1;
            }
            else if (t.Left != null && t.Right != null)
            {
                //默认用其右子树的最小数据代替该节点的数据并递归的删除那个节点
                AVLTreeNode <K> min = t.Right;
                while (min.Left != null)
                {
                    min = min.Left;
                }
                //t.Key = findMin(t.right).Key;
                t.Key   = min.Key;
                t.Right = Remove(t.Key, t.Right);
                t       = BalanceChild(t);
                //完了之后更新height值
                t.Height = Math.Max(Height(t.Left), Height(t.Right)) + 1;
            }
            else
            {
                t = (t.Left != null) ? t.Left : t.Right;
            }
            return(t);
        }
Beispiel #12
0
        private AVLTreeNode <K> mRoot;           // 根结点

        public AVLTree()
        {
            mRoot = null;
        }
Beispiel #13
0
        public bool Remove(T value)
        {
            AVLTreeNode <T> current;

            current = Find(value); // поиск удаляемого значения

            if (current == null)
            {
                return(false);
            }

            if (current.Right == null)      // если нет правого потомка
            {
                if (current.Parent == null) // удаляемый узел является корнем
                {
                    Head = current.Left;    //на место корня перемещаем левый потомок
                    if (Head != null)
                    {
                        Head.Parent = null; // для данного корня удаляем ссылку на родителя
                    }
                }
                else
                {
                    int result = current.Parent.CompareTo(current.Value);
                    if (result > 0)
                    {
                        current.Parent.Left = current.Left;
                    }
                    else if (result < 0)
                    {
                        current.Parent.Right = current.Left;
                    }
                }
            }

            else if (current.Right.Left == null)
            {
                current.Right.Left = current.Left;

                if (current.Parent == null)
                {
                    Head = current.Right;

                    if (Head != null)
                    {
                        Head.Parent = null;
                    }
                    else
                    {
                        int result = current.Parent.CompareTo(current.Value);
                        if (result > 0)
                        {
                            current.Parent.Left = current.Right;
                        }
                        else if (result < 0)
                        {
                            current.Parent.Right = current.Right;
                        }
                    }
                }
            }

            else
            {
                AVLTreeNode <T> leftmost = current.Right.Left;

                while (leftmost.Left != null)
                {
                    leftmost = leftmost.Left;
                }
                leftmost.Parent.Left = leftmost.Right;
                leftmost.Left        = current.Left;
                leftmost.Right       = current.Right;

                if (current.Parent == null)
                {
                    Head = leftmost;
                    if (Head != null)
                    {
                        Head.Parent = null;
                    }
                }
                else
                {
                    int result = current.Parent.CompareTo(current.Value);
                    if (result > 0)
                    {
                        current.Parent.Left = leftmost;
                    }
                    else if (result < 0)
                    {
                        current.Parent.Right = leftmost;
                    }
                }
            }
            return(true);
        }
Beispiel #14
0
 public AVLTree(AVLTreeNode <T> root)
 {
     _root = root;
 }
Beispiel #15
0
        private void DrawTreeNode(Graphics g, PointF p, AVLTreeNode <int> node, bool highlight)
        {
            if (node != null)
            {
                string text = node.Value.ToString();
                SizeF  size = g.MeasureString(text, _font);

                float ellipseWidth  = RADIUS + size.Width;
                float ellipseHeight = RADIUS + size.Height;

                float left = p.X - ellipseWidth / 2;
                float top  = p.Y - ellipseHeight / 2;

                Pen pen = _penNormal;


                if (node.CheckLeftChild)
                {
                    PointF p1 = p;
                    PointF p2 = p;

                    p1.X = left + ellipseWidth / 2;


                    p2.X -= (node.Value - node.LeftChild.Value) * _ratio;

                    p2.Y += VER_DISTANCE;

                    bool hlight = false;

                    if (_queue != null && _queue.Count > 0)
                    {
                        if (_queue.Peek() == node.LeftChild.Value)
                        {
                            _queue.Dequeue();
                            pen    = _penHighLight;
                            hlight = true;
                        }
                    }
                    g.DrawLine(pen, p1, p2);

                    DrawTreeNode(g, p2, node.LeftChild, hlight);

                    if (p2.X < _minLeft)
                    {
                        _minLeft = p2.X;
                    }
                    if (p2.X > _maxLeft)
                    {
                        _maxLeft = p2.X;
                    }
                }
                if (node.CheckRightChild)
                {
                    PointF p1 = p;
                    PointF p2 = p;
                    p1.X = left + ellipseWidth / 2;

                    p2.X += (node.RightChild.Value - node.Value) * _ratio;

                    p2.Y += VER_DISTANCE;

                    pen = _penNormal;
                    bool hlight = false;
                    if (_queue != null && _queue.Count > 0)
                    {
                        if (_queue.Peek() == node.RightChild.Value)
                        {
                            _queue.Dequeue();
                            pen    = _penHighLight;
                            hlight = true;
                        }
                    }
                    g.DrawLine(pen, p1, p2);

                    DrawTreeNode(g, p2, node.RightChild, hlight);

                    if (p2.X < _minLeft)
                    {
                        _minLeft = p2.X;
                    }
                    if (p2.X > _maxLeft)
                    {
                        _maxLeft = p2.X;
                    }
                }

                pen = highlight ? _penHighLight : _penNormal;

                g.FillEllipse(_brush, left, top, ellipseWidth, ellipseHeight);
                g.DrawEllipse(pen, left, top, ellipseWidth, ellipseHeight);

                g.DrawString(text, _font, Brushes.Black, left + RADIUS / 2, top + RADIUS / 2);
            }
        }
Beispiel #16
0
 private AVLTreeNode <K> LeftAndRightRotate(AVLTreeNode <K> t)
 {
     t.Left = LeftRotate(t.Left);
     return(RightRotate(t));
 }
Beispiel #17
0
 public AVLTree(int Value)
 {
     root = new AVLTreeNode(Value);
 }
 public void Initialize()
 {
     _tree = new AVLTree <int, string>();
     _root = _tree.Build(Constants.KeyValues);
 }