删除:单旋
如果要删除T3下的节点,可以进行一次右旋操作,但要注意的是,如果T0,T1和T2下面都有节点,那么旋转操作过后,高度不变所以并不会失衡。但如果T0,T1存在,T2不存在,那么旋转之后此子树的高度会减少1,那么它的祖先就会失衡。所以 g经单旋调整后复衡,子树高度未必复原;更高的祖先仍可能失衡。因有失衡传播现象,可能需要做次调整
删除:多旋
代码如下
//AVL树在del之后进行rebalance操作,从插入节点的父节点开始,逐层向上遍历进行rebalance,直到遍历到根节点,由于树是平衡的,所以rebalance的时间复杂度是O(logn)。
void rebalance(AVLNode* a){
setBalance(a);
if(a->balance== -2){ //如果左子树比右子树高2层,需要通过旋转来重新平衡
if(a->left->balance <=0){ //如果左子节点的左子树比右子树高,则进行一次右旋;如果左子节点的右子树比左子树高,则先进行左旋,再进行右旋。
a=turnRight(a);
}else{
a=turnLeftThenRight(a);
}
}else if(a->balance==2){ //如果右子树比左子树高2层,需要通过旋转来重新平衡
if(a->right->balance>=0){ //如果右子节点的右子树比左子树高,则进行一次左旋;如果右子节点的右子树比左子树低,则先进行右旋,再进行左旋。
a=turnLeft(a);
}else{
a=turnRightThenLeft(a);
}
}
if(a->parent){
rebalance(a->parent);
}else{
tree.root=a;
}
}
void delnodeifhas1childornot(AVLNode* a){ // 在BST树的基础上加了rebalance操作
if(a->parent==0){
if(a->left){
tree.root=a->left;
a->left->parent=0;
}else{
tree.root=a->right;
a->right->parent=0;
}
}else{
if(a->parent->left==a){
if(a->left){
a->parent->left=a->left;
a->left->parent=a->parent;
}else{
a->parent->left=a->right;
if(a->right)
a->right->parent=a->parent;
}
}else{
if(a->left){
a->parent->right=a->left;
a->left->parent=a->parent;
}else{
a->parent->right=a->right;
if(a->right)
a->right->parent=a->parent;
}
}
rebalance(a->parent);
}
}
struct AVLNode* getmin(AVLNode* a){
if(a->left)
getmin(a->left);
else
return a;
}
void delnodeifhas2child(AVLNode* a){
AVLNode* after=getmin(a->right);
a->value=after->value;
delnodeifhas1childornot(after);
}
void del(int value,AVLNode* root){ //删除操作
AVLNode* node=select(value,root);
if(node->value==value){
if(node->left&&node->right){
delnodeifhas2child(node);
}else{
delnodeifhas1childornot(node);
}
}
}