AVL树的删除比插入更加耗时与复杂,主要表现在使用复制删除删除掉某个节点后,经过旋转,重新平衡之后,子树的高度可能发生变化,因此需要继续向上追溯,对父节点重新评估是否需要做重新平衡。是否需要平衡的原则是看balance value,只要出现+2或者-2就需要旋转与重新平衡。是否向上追溯取决于子树的高度是否减少,只要子树高度降低,就需要向上追溯。
情况一: 不旋转,不追溯。
情况二:不旋转,向上追溯。
情况三:单旋转,不追溯。
情况四:单旋转,向上追溯。
情况五:双旋转,向上追溯。该情况下面,最下面两棵子树不可能高度均为h-2,因为q节点的balance value必为-1。
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;
}