平衡二叉树(AVL 树)
1.平衡二叉树的定义
平衡二叉树任然是一棵二叉查找树,所谓平衡是指,对 AVL 树的任意结点来说,其左子树与右子树的高度之差的绝对值不超过 1,其中左子树与右子树的高度之差称为该节点的平衡因子
由于需要对每个结点都得到平衡因子,因此需要在树的结构中加入一个变量 height 来记录以当前为根结点的子树的高度:
struct node{
int v,height; //v 为权值,height 为当前子树高度
node* lchild;
node* rchild;
};
在这种定义下,如果需要新建一个结点,就可以采用如下写法:
node* newNode(int v){
node* Node = new node;
Node->v = v;
Node->height = 1; //结点初始高度为 1
Node->lchild = Node->rchild = NULL;
return Node;
}
可以根据下面的函数获取结点 root 所在子树的当前高度:
int getHeight(node* root){
if(root == NULL) return 0; //空结点高度为 0
return root->height;
}
根据定义,可以通过下面的函数计算平衡因子:
int getBalanceFactor(node* root){
//左子树高度减右子树高度
return getHeight(root->lchild) - getHeight(root->rchild);
}
显然结点 root 所在子树的 height 等于其左子树的 height 与右子树的 height 的较大值加 1,因此可以通过下面的函数来更新 height:
void updateHeight(node* root){
//结点 root 的高度等于左子树和右子树高度的最大值加 1
root->height = max(getHeight(root->lchild),getHeight(root->rchild)) + 1;
}
2.平衡二叉树的基本操作
1. 查找操作
由于平衡二叉树是一棵二叉查找树,因此其查找操作与二叉查找树相同。
void search(node* root,int x){ //查找权值为 x 的结点
if(root == NULL){
cout<<"查找失败!"<<endl;
return;
}
if(x == root->data){
cout<<root->data<<endl;
}else if(x < root->data){
search(root->lchild,x);
}else{
search(root->rchild,x);
}
}
2.插入操作
- 左旋:
//左旋(Left Rotation)
void LR(node* &root){
if(root->rchild != NULL){
node* temp = root->rchild;
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
}
- 右旋:
//右旋(Right Rotation)
void RR(node* &root){
if(root->lchild != NULL){
node* temp = root->lchild;
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
}
AVL树的插入分为 LL型、LR型、RR型、RL型:
在这个基础上,由于需要插入的结点开始从下往上判断结点是否失衡,因此需要在每个 insert 函数之后更新当前子树的高度,并在这之后根据树型是 LL 型、LR型、RR型、RL型之一来进行平衡操作:
//插入权值为 v 的结点
void insert(node* &root,int v){
if(root == NULL){ //到达空结点
root = newNode(v);
return;
}
if(v < root->v){
insert(root->lchild,v);
updateHeight(root); //更新树高
if(getBalanceFactor(root) == 2){
if(getBalanceFactor(root->lchild) == 1)//LL型
RR(root);
else if(getBalanceFactor(root->lchild) == -1){//LR
LR(root->lchild);
RR(root);
}
}
}
else {
insert(root->rchild,v);
updateHeight(root);
if(getBalanceFactor(root) == -2){
if(getBalanceFactor(root->rchild) == -1){//RR
LR(root);
}else if(getBalanceFactor(root->rchild) == 1){//RL
RR(root->rchild);
LR(root);
}
}
}
}
3.AVL 树的建立
node* create(int data[],int n){
node* root = NULL; //新建空结点
for(int i = 0;i < n;i++){
insert(root,data[i]); //将 data[0]-data[n-1] 插入 AVL 树
}
return root;
}