在删除某节点之前我们需要找到该节点的位置,因此寻找节点的过程可分为以下3种情况(假设我们要找的节点值为data,当前节点为note):
1、note的值<data,则应该在该节点的左子树寻找。在左子树中删除该节点成功后,需要调整平衡二叉树,以保持平衡。如果删除节点后(在左子树中删除节点,左子树高度不变或变矮),note节点的平衡因子为-2,说明删除后note的右子树导致note不平衡,则需要调整note的右子树(如果note右孩子节点的右子树高度大于左子树高度,进行RR调整,如果note右孩子节点的左子树高度大于有子树高度,进行RL调整)。
2、note的值>data,则应该在该节点的右子树寻找。在右子树中删除该节点成功后,需要调整平衡二叉树,以保持平衡。如果删除节点后(在右子树中删除节点,右子树高度不变或变矮),note节点的平衡因子为2,说明删除后note的左子树导致note不平衡,则需要调整note的左子树(如果note左孩子节点的右子树高度大于左子树高度,进行LR调整,如果note左孩子节点的左子树高度大于有子树高度,进行LL调整)。
3、note的值=data,找到!然后我们就可以进行删除了,但是平衡二叉树某节点的删除又分为以下4种情况:
1、该节点没有左、右孩子。直接删除该节点=NULL。
2、该节点只有左孩子。将其左孩子的值复制到该节点(仅移动值即可),直接删除其左孩子。
3、该节点只有右孩子。将其右孩子的值复制到该节点(仅移动值即可),直接删除其右孩子。
4、该节点既有左孩子又有右孩子,则分为以下两种情况:
-
- 该节点左子树的高度大于右子树,找到该节点左孩子的最右节点right,将right的值复制到该节点,然后删除最右节点right。
- 该节点右子树的高度大于左子树,找到该节点右孩子的最左节点left,将left的值复制到该节点,然后删除最左节点left。
最后,附上测试代码与结果:
bool AVLDelete(BSTNode *&T,int find)
{
BSTNode *post,*pre;
if (T==NULL)
{
return false;
}
else
if(T->data == find)
{
if (T->lchild==NULL && T->rchild==NULL)
{
T = NULL;
}
else
if (T->lchild!=NULL && T->rchild == NULL)
{
T = T->lchild;
}
else
if (T->rchild!=NULL && T->lchild == NULL)
{
T= T->rchild;
}
else
{
if (Height(T->lchild) > Height(T->rchild)
{
pre = T->lchild;
while(pre->rchild)
{
pre = pre->rchild;
}
T->data = pre->data;
AVLDelete((T->lchild),pre->data);
}
else
{
post = T->rchild;
while(post->lchild)
{
post = post->lchild;
}
T->data = post->data;
AVLDelet((T->rchild),post->data);
}
}
return true;
}
else
if (find < T->data)
{
if (!AVLDelete(T->lchild,find))
{
return false;
}
else
{
T->height = Max(Height(T->lchild),Height(T->rchild))+1;
if (Height(T->lchild)-Height(T->rchild)== -2)
{
if (Height(T->rchild->lchild) > Height(T->rchild->rchild))
{
modifiedRL(T);
}
else
{
modifiedRR(T);
}
}
}
return true;
}else
{
if (!AVLDelete(T->rchild,find))
{
return false;
}
else
{
T->height = Max(Height(T->lchild),Height(T->rchild))+1;
if (Height(T->lchild)-Height(T->rchild)== 2)
{
if (Height(T->lchild->lchild) > Height(T->lchild->rchild))
{
modifiedLL(T);
}
else
{
modifiedLR(T);
}
}
}
return true;
}
}
下图片为测试结果(1-16个数字组成的平衡二叉树的先序、中序遍历结果,以及删除8节点后的先序、中序遍历结果。)