PAT甲级 1066 AVL树的根

原题链接

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

猜你喜欢

转载自blog.csdn.net/weixin_45660485/article/details/124911837