AVL树是一种自平衡二叉搜索树。
在AVL树中,任何节点的两个子树的高度最多相差 1 个。
如果某个时间,某节点的两个子树之间的高度差超过 1,则将通过树旋转进行重新平衡以恢复此属性。
图 1−4 说明了旋转规则。
现在,给定插入序列,请你求出 AVL 树的根是多少。
输入格式
第一行包含整数 N,表示总插入值数量。第二行包含 N 个不同的整数,表示每个插入值。
输出格式
输出得到的 AVL 树的根是多少。数据范围
1≤N≤20
输入样例1:
5
88 70 61 96 120
输出样例1:
70
输入样例2:
7
88 70 61 96 120 90 65
输出样例2:
88
我的解法:
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int v[N], l[N], r[N], h[N];
int idx;
void update(int u){ // 更新节点深度
h[u] = max(h[l[u]], h[r[u]]) + 1;
}
int get_balance(int u){ // 左右平衡判断
return h[l[u]] - h[r[u]];
}
void R(int &u){ // 右旋
int p = l[u];
l[u] = r[p];
r[p] = u;
update(u), update(p);
u = p;
}
void L(int &u){ // 左旋
int p = r[u];
r[u] = l[p];
l[p] = u;
update(u), update(p);
u = p;
}
void insert(int &u, int w){
if(!u){
u = ++idx;
v[u] = w;
update(u);
}
else if(w <= v[u]){
insert(l[u], w);
if(get_balance(u) == 2){
if(get_balance(l[u]) == 1){
R(u);
}
else{
L(l[u]), R(u);
}
}
}
else{
insert(r[u], w);
if(get_balance(u) == -2){
if(get_balance(r[u]) == -1){
L(u);
}
else{
R(r[u]), L(u);
}
}
}
update(u);
}
int main(){
int n;
cin >> n;
int root = 0;
for(int i = 0; i < n; i ++ ){
int w;
cin >> w;
insert(root, w);
}
cout << v[root];
return 0;
}
收获:
avl树操作的核心是左旋和右旋操作,可以画一张图来捋顺自己的思路
使用h数组来记录每个节点的深度,每次旋转操作后都要更新节点深度,节点更新采用update方法,当前节点的深度为左子树和右子树深度的最大值+1