平衡二叉树AVL及相关操作

平衡二叉树AVL的定义

· AVL树使得树的高度在每次插入元素后仍能保持O(logn)的级别
· AVL树仍然是一棵二叉查找树,所谓“平衡”是指,对AVL树的任意结点来说,其左子树与右子树的高度之差(平衡因子)的绝对值不超过1
· 由于需要对每个结点都得到平衡因子,因此需要在树的结构中加入一个变量height来记录当前结点为根结点的子树高度

1
2
3
4
struct node{
int v,height;
node *lchild,*rchild;
};

在该定义下新建结点时需增设高度初始值为1;

1
2
3
4
5
6
7
node* newNode(int v){
node* Node=new node;
Node->v=v;
Node->height=1;
Node->lchild=Node->rchild=NULL;
return Node;
}

获取结点root所在子树当前高度:

1
2
3
4
int getHeight(node* root){
if(root==NULL) return 0;
return root->height;
}

计算当前结点root的平衡因子:

1
2
3
int getBalance(node* root){
return getHeight(root->lchild)-getHeight(root->rchild); //左减右
}

更新root的height:

1
2
3
void updataHeight(node* root){
root->height=max(getHeight(root->lchild),getHeight(root->rchild))+1;
}

· 之所以不直接记录结点的平衡因子是因为没有办法通过当前结点的子树的平衡因子求得该结点的平衡因子,而需要借助子树的高度间接求得。而结点所在子树的height可以直接取左右子树height的较大值加1

平衡二叉树的基本操作

1.查找操作

和二叉查找树是一样的~

2.插入操作

首先了解两个调整过程:左旋和右旋
(先贴代码以后补图)

1
2
3
4
5
6
7
8
9
//左旋(Left Rotation)
void L(node* &root){
node* temp=root->rchild; //脑补画面
root->rchild=temp->lchild;
temp->lchild=root;
updataHeight(root); //一定要先跟新root因为此root左旋后降了一层
updataHeight(temp);
root=temp;
}

1
2
3
4
5
6
7
8
9
//右旋(Right Rotation)
void R(node* &root){
node* temp=root->lchild;
root->lchild=temp->rchild;
temp->rchild=root;
updataHeight(root);
updataHeight(temp);
root=temp;
}

回到结点插入问题,在插入结点时,只要把最靠近插入结点的失衡结点调整到正常,路径上的所有结点都会平衡。
最靠近插入结点的失衡结点的平衡因子只有可能是2或-2,各自对应两种树型(LL,LR)和(RR,RL) (待补图)

LL BF(root)=2,BF(root->lchild)=1 对root右旋
LR BF(root)=2,BF(root->lchild)=-1 先对root->lchild左旋,后对root右旋
RR BF(root)=-2,BF(root->lchild)=-1 对root左旋
RL BF(root)=-2,BF(root->lchild)=1 先对root->lchild右旋,后对root左旋
(BF为BalanceFactor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//AVL树插入权值为v的结点
void insert(node* &root,int v){
if(root==NULL){
root=newNode(v);
return;
}
if(v<root->v){
insert(root->lchild,v);
updataHeight(root);
if(getBalance(root)==2){
if(getBalance(root->lchild)==1){
R(root);
}else if(getBalance(root->lchild)==-1){
L(root->lchild);
R(root);
}
}
}else{
insert(root->rchild,v);
updataHeight(root);
if(getBalance(root)==-2){
if(getBalance(root->lchild)==-1){
L(root);
}else if(getBalance(root->lchild)==1){
R(root->lchild);
L(root);
}
}
}
}

3.AVL树的建立

调用插入函数依次插入即可,同二叉查找树

【摘自《算法笔记》……