题目描述
知识点: 二叉搜索树,AVL树
思路: 本题就是一个构建AVL树的模板题,现模板如下:
- l,r数组表示某个节点的左右孩子。v用于存放节点值。h用于存放每个节点的高度
- 两种旋转操作实现:
void L(int &u){//左旋
int p = r[u];
r[u] = l[p];
l[p] = u;
u = p;
}
void R(int &u){//右旋
int p = l[u];
l[u] = r[p];
r[p] = u;
u = p;
}
对于左旋,就是先把根的左子树记录下来。然后左子树的根作为根,它的右子树连接到根上。原先的根左子树连接左子树的右子树。…十分绕,看图。右旋就是反过来,看图就好了。
- 四种情况的旋转:
(1)LL型:对根节点右旋 (2)RR型:对根节点左旋 (3)LR型:首先对左子树的根左旋然后对根节点右旋 (4)RL型:首先对右子树的根右旋然后对根节点左旋
对于如何判断插入类型: 如果是某个节点失衡,即它的左子树高了。则判断它的左子树,若它的左子树的左子树比右子树高度小1,则是LR型,若>1则是LL型,不可能相等。因为已经失衡。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 50;
int l[N],r[N],v[N],h[N],idx,n;
void R(int &u){//右旋
int p = l[u];
l[u] = r[p];
r[p] = u;
u = p;
}
void L(int &u){//左旋
int p = r[u];
r[u] = l[p];
l[p] = u;
u = p;
}
int update(int u){//更新树的高度
if(u == 0) return 0;
else h[u] = max(update(l[u]),update(r[u]))+1;
return h[u];
}
int get_balance(int u){//求某个节点的左右子树高度之差
return h[l[u]] - h[r[u]];
}
void insert(int &u,int x){
if(!u){
u = ++idx;
v[u] = x;
}else{
if(v[u] > x){//插入左边
insert(l[u],x);
if(get_balance(u) >= 2){//发生了不平衡
if(get_balance(l[u]) >= 1) //LL型
R(u);
else{
L(l[u]);
R(u);
}
}
}else{//插入右边
insert(r[u],x);
if(get_balance(u) <= -2){
if(get_balance(r[u]) <= -1) //RR型
L(u);
else{
R(r[u]);
L(u);
}
}
}
}
update(u);
}
int main(){
cin>>n;
int root = 0;
while(n--){
int v;
cin>>v;
insert(root,v);
}
cout<<v[root];
return 0;
}