单旋插入
插入节点c,若节点c小于b,则成为b的左子节点,此时a左子树深度为2,右子树深度为0,处于不平衡状态,此时执行右旋操作。
右旋就是使a、b进行右旋1/4圆,使得b节点作为父节点,a节点变为b节点的右节点,b的左子树在经过右旋操作后仍是b的左子树。
如果b有右子树。那么右旋后b的右子树将成为a的左子树。
左旋操作与右旋操作相同
注意,g经过单旋调整后复衡,子树的高度复原,更高祖先也必然平衡,全树复衡
左旋代码
struct AVLNode* turnLeft(AVLNode* a){
//左旋把a的父节点的子节点替换为b
AVLNode* b=a->right;
if(a->parent!=0){
if(a->parent->right==a){
a->parent->right=b;
}else{
a->parent->left=b;
}
}
b->parent=a->parent;
//将a作为b的左子树,并将b的左子树作为a的右子树
a->parent=b;
a->right=b->left;
b->left=a;
if(a->right!=0)
a->right->parent=a;
//重新设置a\b的balance值
setBalance(a);
setBalance(b);
//返回b节点
return b;
}
右旋代码
struct AVLNode* turnRight(AVLNode* a){
// 右旋使a的父节点的子节点替换为b
AVLNode* b=a->left;
if(a->parent!=0){
if(a->parent->right==a){
a->parent->right=b;
}else{
a->parent->left=b;
}
}
b->parent=a->parent;
//将b的右子树作为a的左子树,并将a作为b的右子树
a->parent=b;
a->left=b->right;
if(a->left!=0)
a->left->parent=a;
b->right=a;
//重新设置a、b节点的balance值
setBalance(a);
setBalance(b);
//返回b节点
return b;
}
双旋插入
如果节点插入到a的左子树的右节点,则需要先左旋再右旋来重新平衡树。同理,如果节点插入到a的右子树的左子节点,则需要先右旋再左旋来重新平衡树。
代码
struct AVLNode* turnLeftThenRight(AVLNode* a){
a->left = turnLeft(a->left);
return turnRight(a);
}
struct AVLNode* turnRightThenLeft(AVLNode* a){
a->right = turnRight(a->right);
return turnLeft(a);
}