AVL树实现细节讲解

大佬的一篇文章
练习题
平衡二叉树最常见的操作就是左旋和右旋操作的实现以及何时左旋和右旋
1.左旋与右旋操作

2.需要进行旋转的情形

3.左旋和右旋在实现时需要注意跟新高度,同时更新根节点的指向
当左旋结点u时,参考第一张图片右边的B这一点,旋转时E,C,D的高度不会改变,而A,B则会改变,但是要先update(B);再update(A);
当右旋结点u时,参考第一张图片左边的A这一点,旋转时E,C,D的高度不会改变,而A,B则会改变,但是要先update(A);再update(B);
在更新完了之后我们需要将u指向新的根节点,因为此时当前树根节点发生了变化。
4.插入操作需要牢记的几点
①insert(int &u,int k);要使用引用,这样方便加入新的结点。
②insert的功能是在以u为根节点的树中插入k,然后插入完成后要更新u的
③之前实现一个比较易错的地方:在插入后,可能会进行L或者R的操作来调整u树,如果是这样,那么update是没有必要的,但是如果不需要调整时,这时不在最后写update会造成u没有调整高度而导致出错,还有一点是在向u插入k时,如果到达末尾了,也就是u为0了,新建了一个点,这时最后的update的作用也可以帮助更新h[u]=1,因此insert最后update(u)是必须的。
5.代码实现

#include<bits/stdc++.h>
using namespace std;
const int N = 30;
int h[N],l[N],r[N],w[N],idx = 1,root,n,a[N];
void update(int u){
    
    
    h[u] = max(h[l[u]],h[r[u]])+1;
}
void L(int &u){
    
    
    int p = r[u];
    r[u] = l[p],l[p] = u;
    update(u);update(p);u = p;
}
void R(int &u){
    
    
    int p = l[u];
    l[u] = r[p],r[p] = u;
    update(u);update(p);u = p;
}
int get_balance(int u){
    
    
    return h[l[u]]-h[r[u]];
}
void insert(int &u,int k){
    
    
    if(!u) w[idx] = k,u = idx++;
    else if(k<w[u]){
    
    
        insert(l[u],k);
        if(get_balance(u)==2){
    
    
            if(get_balance(l[u])==1){
    
    
                R(u);
            }else{
    
    
                L(l[u]);R(u);
            }
        }
    }else{
    
    
        insert(r[u],k);
        if(get_balance(u)==-2){
    
    
            if(get_balance(r[u])==-1){
    
    
                L(u);
            }else{
    
    
                R(r[u]);L(u);
            }
        }
    }
    update(u);
}
int main(){
    
    
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n;i++){
    
    
        insert(root,a[i]);
    }
    cout<<w[root]<<endl;
}

猜你喜欢

转载自blog.csdn.net/qq_44932835/article/details/119971017