一,什么是平衡二叉树?
平衡二叉树又称为AVL树,它是一棵空树,或是满足下列性质的二叉排序树。其左子树与右子树都是平衡二叉树,且左右子树深度之差的绝对值不超过1。
二,向左与向右旋转
1,向左旋转
以A为支点,向左旋转,A节点放在左孩子节点的位置上。
2,向右旋转
以A为支点,向右旋转,A节点放在右孩子节点的位置上。
三,平衡二叉树的插入操作
假定向平衡二叉树中插入一个节点破坏了平衡二叉树的平衡性,首先找出插入新节点后失去平衡的最小子树的根节点,然后进行调整,调整操作可以归纳为下面四种情况:
1,LL型调整
情况1:在A节点的左孩子(设为B节点),的左子树上插入节点,使A失去平衡。
调整方法:以A节点为支点,向右旋转。
2,RR型调整
情况2:在A节点的右孩子(设为B节点),的右子树上插入节点,使A失去平衡。
调整方法:以A节点为支点,向左旋转。
3,LR型调整
情况3:在A节点的左孩子(设为B节点),的右子树上插入节点,使A失去平衡。
调整方法:首先以B为支点,向左旋转;然后,以A为支点,向右旋转。
4,RL型调整
情况4:在A节点的右孩子(设为B节点),的左子树上插入节点,使A失去平衡。
调整方法:首先以B为支点,向右旋转;然后,以A为支点,向左旋转。
四,平衡二叉树性能
在一棵平衡二叉树上的查找过程和在二叉排序树上的查找过程相同,因此,在平衡二叉树上进行查找关键字的比较次数不会超过平衡二叉树的深度。可以证明,含有 n 个节点的平衡二叉树的最大深度为Ologn,因此,平衡二叉树的平均查找长度为Ologn。
五,算法实现
1,节点的数据结构
struct AVLTreeNode{
int data;
int height;
AVLTreeNode *lchild;
AVLTreeNode *rchild;
};
2,向右旋转的操作,解决LL型问题
//右旋
AVLTreeNode* rightRotate(AVLTreeNode *root){
AVLTreeNode *lchild = root->lchild;
root->lchild = lchild->rchild;
lchild->rchild = root;
root->height = Max(Height(root->lchild), Height(root->rchild)) + 1;
lchild->height = Max(Height(lchild->lchild), root->height) + 1;
return lchild;
}
3,向左旋转的操作,解决RR型问题
//左旋
AVLTreeNode* leftRotate(AVLTreeNode *root){
AVLTreeNode* rchild = root->rchild;
root->rchild = rchild->lchild;
rchild->lchild = root;
root->height = Max(Height(root->lchild), Height(root->rchild)) + 1;
rchild->height = Max(Height(rchild->rchild), root->height) + 1;
return rchild;
}
4,先左旋,后右旋,解决LR型问题
AVLTreeNode* LRRotate(AVLTreeNode *root){
root->lchild = leftRotate(root->lchild);
return rightRotate(root);
}
5,先右旋,后左旋,解决RL型问题
AVLTreeNode* RLRotate(AVLTreeNode *root){
root->rchild = rightRotate(root->rchild);
return leftRotate(root);
}
6,节点的插入操作
//Insert
AVLTreeNode* Insert(AVLTreeNode *&root, int x){
if(root == NULL){
root = new AVLTreeNode();
root->data = x;
root->height = 0;
root->lchild = NULL;
root->rchild = NULL;
} else if(x < root->data){ //左子树插入新节点
root->lchild = Insert(root->lchild, x);
if(Height(root->lchild) - Height(root->rchild) == 2){ //左子树插入节点所以高度是左子树高于右子树
if(x < root->lchild->data){ //LL
root = rightRotate(root);
} else { //LR
root = LRRotate(root);
}
}
} else if(x > root->data){ //右子树插入新节点
root->rchild = Insert(root->rchild, x);
if(Height(root->rchild) - Height(root->lchild) == 2){ //右子树插入节点所以高度是右子树高于左子树
if(x > root->rchild->data){ //RR
root = leftRotate(root);
} else { //RL
root = RLRotate(root);
}
}
}
root->height = Max(Height(root->lchild), Height(root->rchild)) + 1;
return root;
}