C++模板实现二叉树(七 AVL树的删除)

AVL树的删除比插入更加耗时与复杂,主要表现在使用复制删除删除掉某个节点后,经过旋转,重新平衡之后,子树的高度可能发生变化,因此需要继续向上追溯,对父节点重新评估是否需要做重新平衡。是否需要平衡的原则是看balance value,只要出现+2或者-2就需要旋转与重新平衡。是否向上追溯取决于子树的高度是否减少,只要子树高度降低,就需要向上追溯。

情况一: 不旋转,不追溯。
《C++模板实现二叉树(七 AVL树的删除)》

情况二:不旋转,向上追溯。
《C++模板实现二叉树(七 AVL树的删除)》

情况三:单旋转,不追溯。
《C++模板实现二叉树(七 AVL树的删除)》

情况四:单旋转,向上追溯。
《C++模板实现二叉树(七 AVL树的删除)》

情况五:双旋转,向上追溯。该情况下面,最下面两棵子树不可能高度均为h-2,因为q节点的balance value必为-1。
《C++模板实现二叉树(七 AVL树的删除)》

template <class T, unsigned int capacity>
void BinSearchTreeAVL<T, capacity>::updateBalanceFactors4Delete(AVLNode<T>* avlNode, bool leftOrRight)
{
    //For delete, the avlNode should be the pa Node, leftOrRight means the del node is 
    //pa's left or right
    if (NULL == avlNode)
    {

    }
    else
    {
        if (leftOrRight)     //Left
        {
            if (0 == avlNode->balanceValue)
            {
                avlNode->balanceValue = 1;
            }
            else if (-1 == avlNode->balanceValue)
            {
                avlNode->balanceValue = 0;
                //Go up
                AVLNode<T>* pa = avlNode->pa;
                if (NULL != pa)
                {
                    if (avlNode == pa->getLeft())
                    {
                        updateBalanceFactors4Delete(pa, true);
                    }
                    else
                    {
                        updateBalanceFactors4Delete(pa, false);
                    }
                }
            }
            else
            {
                //if (null == dynamic_cast<AVLNode<T>*>(avlNode->getRight()))
                //{
                // avlNode->balanceValue = 0;
                //}
                //rotation
                //First case, single rotation left
                if (dynamic_cast<AVLNode<T>*>(avlNode->getRight())->balanceValue == 0)
                {
                    AVLNode<T>* gr = avlNode->pa;
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(avlNode->getRight());
                    AVLNode<T>* chLeft = dynamic_cast<AVLNode<T>*>(ch->getLeft());
                    rotationLeft(gr, avlNode, ch);
                    avlNode->balanceValue = 1;
                    ch->balanceValue = -1;
                    //Set pa pointer
                    avlNode->pa = ch;
                    ch->pa = gr;
                    if (NULL != chLeft)
                        chLeft->pa = avlNode;
                    //do not need Go up, because the subtree height not changed
                }
                //Second case, still single rotation left
                else if (dynamic_cast<AVLNode<T>*>(avlNode->getRight())->balanceValue == 1)
                {
                    AVLNode<T>* gr = avlNode->pa;
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(avlNode->getRight());
                    AVLNode<T>* chLeft = dynamic_cast<AVLNode<T>*>(ch->getLeft());
                    rotationLeft(gr, avlNode, ch);
                    avlNode->balanceValue = 0;
                    ch->balanceValue = 0;
                    //Set pa pointer
                    if (NULL != chLeft)
                        chLeft->pa = avlNode;
                    avlNode->pa = ch;
                    ch->pa = gr;
                    //Need Go up, becuase the subtree height changed (-1)
                    if (NULL != gr)
                    {
                        if (ch == gr->getLeft())
                        {
                            updateBalanceFactors4Delete(gr, true);
                        }
                        else
                        {
                            updateBalanceFactors4Delete(gr, false);
                        }
                    }
                }
                //Need double rotation
                else
                {
                    AVLNode<T>* grPa = avlNode->pa;
                    //bool leftOrRightFlag = false;
                    //if (grPa != NULL)
                    //{
                    // if (grPa->getLeft() == avlNode)
                    // {
                    // leftOrRightFlag = false;
                    // }
                    // else
                    // {
                    // leftOrRightFlag = true;
                    // }
                    //}
                    //else
                    //{
                    // setRoot(ch);
                    //}
                    AVLNode<T>* gr = avlNode;
                    AVLNode<T>* pa = dynamic_cast<AVLNode<T>*>(gr->getRight());
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(pa->getLeft());
                    int oldChBalanceValue = ch->balanceValue;
                    AVLNode<T>* oldChLeft = dynamic_cast<AVLNode<T>*>(ch->getLeft());
                    AVLNode<T>* oldChRight = dynamic_cast<AVLNode<T>*>(ch->getRight());
                    rotationRight(gr, pa, ch);
                    rotationLeft(grPa, gr, ch);
                    //if (NULL != grPa)
                    //{
                    // if (leftOrRightFlag)
                    // {
                    // grPa->setRight(ch);
                    // }
                    // else
                    // {
                    // grPa->setLeft(ch);
                    // }
                    //}
                    //set pa pointer
                    if (NULL != oldChLeft)
                        oldChLeft->pa = gr;
                    if (NULL != oldChRight)
                        oldChRight->pa = pa;
                    pa->pa = ch;
                    gr->pa = ch;
                    ch->pa = grPa;
                    //set balance value
                    ch->balanceValue = 0;
                    if (oldChBalanceValue == 0)
                    {
                        gr->balanceValue = 0;
                        pa->balanceValue = 0;
                    }
                    else if (oldChBalanceValue == -1)
                    {
                        gr->balanceValue = 0;
                        pa->balanceValue = 1;
                    }
                    else
                    {
                        gr->balanceValue = -1;
                        pa->balanceValue = 0;
                    }
                    //Need go up, because the subtree height changed (-1)
                    if (NULL != grPa)
                    {
                        if (ch == grPa->getLeft())
                        {
                            updateBalanceFactors4Delete(grPa, true);
                        }
                        else
                        {
                            updateBalanceFactors4Delete(grPa, false);
                        }
                    }
                }
            }
        }
        else                 //Right
        {
            if (0 == avlNode->balanceValue)
            {
                avlNode->balanceValue = -1;
            }
            else if (-1 == avlNode->balanceValue)
            {
                //avlNode->balanceValue = -2;
                //rotation
                //First case, single rotation right
                if (dynamic_cast<AVLNode<T>*>(avlNode->getLeft())->balanceValue == 0)
                {
                    AVLNode<T>* gr = avlNode->pa;
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(avlNode->getLeft());
                    AVLNode<T>* chRight = dynamic_cast<AVLNode<T>*>(ch->getRight());
                    rotationRight(gr, avlNode, ch);
                    avlNode->balanceValue = -1;
                    ch->balanceValue = 1;
                    //Set pa pointer
                    if(NULL != chRight)
                        chRight->pa = avlNode;
                    avlNode->pa = ch;
                    ch->pa = gr;
                    //do not need Go up, because the subtree height not changed
                }
                //Second case, still single rotation right,need go up
                else if (dynamic_cast<AVLNode<T>*>(avlNode->getLeft())->balanceValue == -1)
                {
                    AVLNode<T>* gr = avlNode->pa;
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(avlNode->getLeft());
                    AVLNode<T>* chRight = dynamic_cast<AVLNode<T>*>(ch->getRight());
                    rotationRight(gr, avlNode, ch);
                    avlNode->balanceValue = 0;
                    ch->balanceValue = 0;
                    //Set pa pointer
                    if (NULL != chRight)
                        chRight->pa = avlNode;
                    avlNode->pa = ch;
                    ch->pa = gr;

                    //Need Go up, becuase the subtree height changed (-1)
                    if (NULL != gr)
                    {
                        if (ch == gr->getLeft())
                        {
                            updateBalanceFactors4Delete(gr, true);
                        }
                        else
                        {
                            updateBalanceFactors4Delete(gr, false);
                        }
                    }
                }
                //Double rotation
                else
                {
                    AVLNode<T>* grPa = avlNode->pa;
                    //bool leftOrRightFlag = false;
                    //if (grPa != NULL)
                    //{
                    // if (grPa->getLeft() == avlNode)
                    // {
                    // leftOrRightFlag = false;
                    // }
                    // else
                    // {
                    // leftOrRightFlag = true;
                    // }
                    //}
                    //AVLNode<T>* grPa = avlNode->pa;
                    AVLNode<T>* gr = avlNode;
                    AVLNode<T>* pa = dynamic_cast<AVLNode<T>*>(gr->getLeft());
                    AVLNode<T>* ch = dynamic_cast<AVLNode<T>*>(pa->getRight());
                    int oldChBalanceValue = ch->balanceValue;
                    AVLNode<T>* oldChLeft = dynamic_cast<AVLNode<T>*>(ch->getLeft());
                    AVLNode<T>* oldChRight = dynamic_cast<AVLNode<T>*>(ch->getRight());
                    rotationLeft(gr, pa, ch);
                    rotationRight(grPa, gr, ch);
                    //if (NULL != grPa)
                    //{
                    // if (leftOrRightFlag)
                    // {
                    // grPa->setRight(ch);
                    // }
                    // else
                    // {
                    // grPa->setLeft(ch);
                    // }
                    //}
                    //else
                    //{
                    // setRoot(ch);
                    //}
                    //set pa pointer
                    if(NULL != oldChLeft)
                        oldChLeft->pa = pa;
                    if (NULL != oldChRight)
                        oldChRight->pa = gr;
                    pa->pa = ch;
                    gr->pa = ch;
                    ch->pa = grPa;
                    //set balance value
                    ch->balanceValue = 0;
                    if (oldChBalanceValue == 0)
                    {
                        gr->balanceValue = 0;
                        pa->balanceValue = 0;
                    }
                    else if (oldChBalanceValue == -1)
                    {
                        gr->balanceValue = 1;
                        pa->balanceValue = 0;
                    }
                    else
                    {
                        gr->balanceValue = 0;
                        pa->balanceValue = -1;
                    }
                    //Need go up, because the subtree height changed (-1)
                    if (NULL != grPa)
                    {
                        if (ch == grPa->getLeft())
                        {
                            updateBalanceFactors4Delete(grPa, true);
                        }
                        else
                        {
                            updateBalanceFactors4Delete(grPa, false);
                        }
                    }
                }
            }
            else
            {
                avlNode->balanceValue = 0;
                //Go up
                AVLNode<T>* pa = avlNode->pa;
                if (NULL != pa)
                {
                    if (avlNode == pa->getLeft())
                    {
                        updateBalanceFactors4Delete(pa, true);
                    }
                    else
                    {
                        updateBalanceFactors4Delete(pa, false);
                    }
                }
            }
        }
    }
    return;
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/luanzheng_365/article/details/70196659
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞