接文章《平衡二叉树的基本操作之插入》,这里给出删除操作的一种是实现。这里借用文章《平衡二叉树(AVL)的插入和删除详解(上)》中的删除思路:
删除的结点不一定是叶子结点,可能是树中的任何一个结点。在二叉查找树中,我们知道删除的结点可能有三种情况:(1)为叶子结点,(2)左子树或右子树有一个为空,(3)左右子树都不空。对第三种情况的处理有三种处理方式,这里采用删除前驱的方式。注意到我们仍然采用的是递归删除,然后判断删除后树是否“变矮”了,然后进行相应的处理。对(1)(2)中情况,很好处理,树的确是“变矮”了。对于第(3)种情况,我们不能直接找到前驱结点,然后把数据拷贝到原本要删除的根结点,最后直接删除前驱结点。因为这么做,我们无法判断原先根结点子树高度的变化情况。所以我们在找到前驱结点后,不是直接删除,而是采用在根结点左子树中递归删除前驱的方式。同样利用文章《平衡二叉树的基本操作之插入》的左旋和右旋函数实现:
bool AVLDelete(AVLTree *root,int x,bool *unbalanced)
{
if(*root == NULL){
return false;
}
else if (x == (*root)->data) {
if ((*root)->lchild == NULL) {
AVLTree t = *root;
*root = (*root)->rchild;
delete t;
*unbalanced = true;
}
else if ((*root)->rchild == NULL) {
AVLTree t = *root;
*root = (*root)->lchild;
delete t;
*unbalanced = true;
}
else {
AVLTree t = (*root)->lchild;
while (t->rchild){
t = t->rchild;
}
(*root)->data = t->data;
AVLDelete(&((*root)->lchild),t->data,unbalanced);
}
}
else if (x < (*root)->data) {
if(!AVLDelete(&((*root)->lchild),x,unbalanced)){
return false;
}
if (*unbalanced) {
switch ((*root)->bf) {
case 1: (*root)->bf = 0;
*unbalanced = true;
break;
case 0: (*root)->bf = -1;
*unbalanced = false;
break;
case -1: rightRotate(root,unbalanced);
}
}
}
else {
if(!AVLDelete(&((*root)->rchild),x,unbalanced)) {
return false;
}
if (*unbalanced) {
switch ((*root)->bf) {
case -1: (*root)->bf = 0;
*unbalanced = true;
break;
case 0: (*root)->bf = 1;
*unbalanced = false;
break;
case 1: leftRotate(root,unbalanced);
}
}
}
return true;
}
测试程序:
int main()
{
AVLTree T = NULL;
bool unbalanced = false;
for(int i = 0; i < 10; i++) {
AVLInsert(&T,i,&unbalanced);
AVLTreeDisplay(T);
cout<<"---------------------cut---------------------"<<endl;
}
int a[] = {7,5,4,3,8,9,2,1,6,0};
for(int i = 0; i < 10; i++){
unbalanced = false;
AVLDelete(&T,a[i],&unbalanced);
AVLTreeDisplay(T);
cout<<"---------------------cut---------------------"<<endl;
}
//AVLTreeDisplay(T);
return 0;
}
测试结果:
0
---------------------cut---------------------
0
\
1
---------------------cut---------------------
1
/ \
0 2
---------------------cut---------------------
1
/ \
0 2
\
3
---------------------cut---------------------
1
/ \
0 3
/ \
2 4
---------------------cut---------------------
3
/ \
1 4
/ \ \
0 2 5
---------------------cut---------------------
3
/ \
1 5
/ \ / \
0 2 4 6
---------------------cut---------------------
3
/ \
1 5
/ \ / \
0 2 4 6
\
7
---------------------cut---------------------
3
/ \
1 5
/ \ / \
0 2 4 7
/ \
6 8
---------------------cut---------------------
3
/ \
1 7
/ \ / \
0 2 5 8
/ \ \
4 6 9
---------------------cut---------------------
3
/ \
1 6
/ \ / \
0 2 5 8
/ \
4 9
---------------------cut---------------------
3
/ \
1 6
/ \ / \
0 2 4 8
\
9
---------------------cut---------------------
3
/ \
1 8
/ \ / \
0 2 6 9
---------------------cut---------------------
2
/ \
1 8
/ / \
0 6 9
---------------------cut---------------------
2
/ \
1 6
/ \
0 9
---------------------cut---------------------
2
/ \
1 6
/
0
---------------------cut---------------------
1
/ \
0 6
---------------------cut---------------------
0
\
6
---------------------cut---------------------
0
---------------------cut---------------------
---------------------cut---------------------
REF:
1,数据结构(C语言版) Ellis Horowitz
2,http://blog.csdn.net/sysu_arui/article/details/7897017