C++模板实现二叉树(六 AVL树基础与旋转)

dsw算法可以从全局平衡树,但是,往往在插入于删除动作发生时,将只影响树的一部分,此时重新平衡可以只在树的一部分进行.AVL树要求每个节点左右子树的高度差最大为1.平衡因子用右子树的高度减去左子树的高度.在AVL树中,平衡因子应该只有-1,0,1三种选择.只要AVL树中任意一个节点的平衡因子小于-1或者大于1,树就要失去平衡.
以下4种情况会导致失去平衡:

  1. 当前节点平衡因子为-1,左子节点的平衡因子为0,在左子节点的左子树中插入节点,导致当前节点的平衡因子变为-2(左子节点-1).通过右旋转使其恢复平衡.
    《C++模板实现二叉树(六 AVL树基础与旋转)》
  2. 当前节点平衡因子为1,右子节点的平衡因子为0,在右子节点的右子树中插入节点,导致当前节点的平衡因子变为2(右子节点1).使用左旋转使其恢复平衡.
    《C++模板实现二叉树(六 AVL树基础与旋转)》
  3. 当前节点平衡因子为-1,左子节点的平衡因子为0,在左子节点的右子树中插入节点,导致当前节点的平衡因子变为-2(左子节点1).使用先左后右旋转使其恢复平衡.
    《C++模板实现二叉树(六 AVL树基础与旋转)》
  4. 当前节点平衡因子为1,右子节点的平衡因子为0,在右子节点的左子树中插入节点,导致当前节点的平衡因子变为2(右子节点-1).使用先右后左旋转使其恢复平衡.(与3对称)

核心代码分析:
在插入节点后,首先更新平衡因子,从插入节点往上依次更新.
碰到更新为-2或2时,即中止,准备开始进行旋转.
如果碰到更新为0时,则中止,不需要旋转.

数据结构上,AVLNode比BinNode需要增加平衡因子和指向父亲的指针。

AVLNode的数据结构:

template <class T>
class AVLNode : public BinNode<T> { public: AVLNode(); AVLNode(const T& data, AVLNode<T> *l = NULL, AVLNode<T> *r = NULL, AVLNode<T> *p = NULL); AVLNode<T>* pa; int balanceValue; AVLNode<T>* left; AVLNode<T>* right; };

对应旋转的代码如下:

template <class T, unsigned int capacity>
void BinSearchTreeAVL<T, capacity>::updateBalanceFactors(AVLNode<T>* avlNode)
{
    if (root == avlNode)
    {
        root->balanceValue = 0;
    }
    else
    {
        AVLNode<T> *pa = avlNode->pa;
        if (pa->left == avlNode)
        {
            pa->balanceValue--;
        }
        else
        {
            pa->balanceValue++;
        }
        while ((root != pa) && (pa->balanceValue != 2) && (pa->balanceValue != -2))
        {
            AVLNode<T> *curr = pa;
            pa = pa->pa;
            if (curr->balanceValue == 0)
            {
                return;       //no need to balance
            }
            else if (curr == pa->left)
            {
                pa->balanceValue--;
            }
            else
            {
                pa->balanceValue++;
            }
        }
        if ((pa->balanceValue == 2) || (pa->balanceValue == -2))
        {
            //rotation to AVL balance
            //the new insert node in right tree right
            if ((pa->balanceValue == 2) && (NULL != pa->right) && (/*static_cast<AVLNode<T>*>*/(pa->right)->balanceValue == 1))
            {
                //update balance value of pa and ch, then rotation left, last update fa pointer
                pa->balanceValue = 0;
                /*static_cast<AVLNode<T>*>*/(pa->right)->balanceValue = 0;
                AVLNode<T>* grNode = pa->pa;
                AVLNode<T>* paNode = pa;
                AVLNode<T>* chNode = /*static_cast<AVLNode<T>*>*/(pa->right);
                AVLNode<T>* chLNode = chNode->left;
                rotationLeft(grNode, paNode, chNode);
                paNode->pa = chNode;
                chNode->pa = grNode;
                if (NULL != chLNode)
                {
                    chLNode->pa = paNode;
                }
            }
            //the new insert node in right tree left
            else if ((pa->balanceValue == 2) && (NULL != pa->right) && (/*static_cast<AVLNode<T>*>*/(pa->right)->balanceValue == -1))
            {
                AVLNode<T>* rotationRGrNode = pa;
                AVLNode<T>* rotationRPaNode = /*static_cast<AVLNode<T>*>*/(pa->right);
                AVLNode<T>* rotationRChNode = /*static_cast<AVLNode<T>*>*/(pa->right->left);
                int rotationRChNodeBalanceValue = rotationRChNode->balanceValue;
                AVLNode<T>* rotationRChRChNode = /*static_cast<AVLNode<T>*>*/(pa->right->left->right);
                rotationRight(rotationRGrNode, rotationRPaNode, rotationRChNode);
                rotationRChNode->pa = rotationRGrNode;
                rotationRPaNode->pa = rotationRChNode;
                if (NULL != rotationRChRChNode)
                {
                    rotationRChRChNode->pa = rotationRPaNode;
                }
                AVLNode<T>* rotationLGrNode = rotationRGrNode->pa;
                AVLNode<T>* rotationLPaNode = rotationRGrNode;
                AVLNode<T>* rotationLChNode = rotationRChNode;
                AVLNode<T>* rotationLChLChNode = /*static_cast<AVLNode<T>*>*/(rotationLChNode->left);
                rotationLeft(rotationLGrNode, rotationLPaNode, rotationLChNode);
                rotationLChNode->pa = rotationLGrNode;
                rotationLPaNode->pa = rotationLChNode;
                if (NULL != rotationLChLChNode)
                {
                    rotationLChLChNode->pa = rotationLPaNode;
                }
                if (1 == rotationRChNodeBalanceValue)
                {
                    rotationRGrNode->balanceValue = -1;
                    rotationRPaNode->balanceValue = 0;
                    rotationRChNode->balanceValue = 0;
                }
                else if (-1 == rotationRChNodeBalanceValue)
                {
                    rotationRGrNode->balanceValue = 0;
                    rotationRPaNode->balanceValue = 1;
                    rotationRChNode->balanceValue = 0;
                }
                else
                {
                    rotationRGrNode->balanceValue = 0;
                    rotationRPaNode->balanceValue = 0;
                    rotationRChNode->balanceValue = 0;
                }

            }
            //the new insert node in left tree left
            else if ((pa->balanceValue == -2) && (NULL != pa->left) && (/*static_cast<AVLNode<T>*>*/(pa->left)->balanceValue == -1))
            {
                //update balance value of pa and ch, then rotation right, last update fa pointer
                /*static_cast<AVLNode<T>*>*/(pa->left)->balanceValue = 0;
                pa->balanceValue = 0;
                AVLNode<T>* grNode = pa->pa;
                AVLNode<T>* paNode = pa;
                AVLNode<T>* chNode = /*static_cast<AVLNode<T>*>*/(pa->left);
                AVLNode<T>* chRNode = chNode->right;
                rotationRight(grNode, paNode, chNode);
                paNode->pa = chNode;
                chNode->pa = grNode;
                if (NULL != chRNode)
                {
                    chRNode->pa = paNode;
                }

            }
            //the new insert node in left tree right
            else if ((pa->balanceValue == -2) && (NULL != pa->left) && (pa->left->balanceValue == 1))          
            {
                AVLNode<T>* rotationLGrNode = pa;
                AVLNode<T>* rotationLPaNode = /*static_cast<AVLNode<T>*>*/(pa->left);
                AVLNode<T>* rotationLChNode = /*static_cast<AVLNode<T>*>*/(pa->left->right);
                int rotationLChNodeBalanceValue = rotationLChNode->balanceValue;
                AVLNode<T>* rotationLChLChNode = /*static_cast<AVLNode<T>*>*/(pa->left->right->left);
                rotationLeft(rotationLGrNode, rotationLPaNode, rotationLChNode);
                rotationLChNode->pa = rotationLGrNode;
                rotationLPaNode->pa = rotationLChNode;
                if (NULL != rotationLChLChNode)
                {
                    rotationLChLChNode->pa = rotationLPaNode;
                }
                AVLNode<T>* rotationRGrNode = rotationLGrNode->pa;
                AVLNode<T>* rotationRPaNode = rotationLGrNode;
                AVLNode<T>* rotationRChNode = rotationLChNode;
                AVLNode<T>* rotationRChRChNode = /*static_cast<AVLNode<T>*>*/(rotationRChNode->right);
                rotationRight(rotationRGrNode, rotationRPaNode, rotationRChNode);
                rotationRChNode->pa = rotationRGrNode;
                rotationRPaNode->pa = rotationRChNode;
                if (NULL != rotationRChRChNode)
                {
                    rotationRChRChNode->pa = rotationRPaNode;
                }
                if (1 == rotationLChNodeBalanceValue)
                {
                    rotationLGrNode->balanceValue = 0;
                    rotationLPaNode->balanceValue = -1;
                    rotationLChNode->balanceValue = 0;
                }
                else if (-1 == rotationLChNodeBalanceValue)
                {
                    rotationLGrNode->balanceValue = 1;
                    rotationLPaNode->balanceValue = 0;
                    rotationLChNode->balanceValue = 0;
                }
                else
                {
                    rotationLGrNode->balanceValue = 0;
                    rotationLPaNode->balanceValue = 0;
                    rotationLChNode->balanceValue = 0;
                }
            }
            else
            {
                //should be error case
            }
        }
    }
    return;
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/luanzheng_365/article/details/69802628
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞