• 一步一步编写AVL树


    第一步:定义结构体

    typedef struct Node{
        int d;        //data
        int h=1;    //height
        struct Node* l=NULL;     
        struct Node* r=NULL; 
        Node(int d=0):d(d){
        }
    }Node; 

    这个结构体和常规的二叉树结构体很相似。但是不同的是多了个属性“h”(height)。用这个属性来记录结点的高度,叶子结点为1,空结点为0 。

    第二部:编写BST树的插入函数

    Node* insert(Node* p,int v){
        Node * node=new Node(v);
        if(!p){
            return node;
        }
        if(v < p->d){    //左子树 
            if(p->l){
                p->l=insert(p->l,v);
            }else{
                p->l=node;
            }
        }else{
            if(p->r){
                p->r=insert(p->r,v);
            }else{
                p->r=node;
            }
        }
    //    setHeight(p); 
        //平衡旋转代码 
    
        //end of 平衡旋转代码 
        return p;
    }

    第三步:编写高度获取与设置的辅助函数

    高度获取:

    int getHeight(Node* node){
        if(node) return node->h;    //如果非空返回这个结点的height 
        return 0;                  //空节点的高度是0 
    }

    高度设置:

    void setHeight(Node* node){    //取左右子树高度的最大值,记得+1 
        node->h=max(getHeight(node->l),getHeight(node->r))+1;
    }

    第四步:编写平衡旋转函数

    当左右子树的height相差为2时,就要调用平衡旋转函数进行旋转。一共有4种旋转模式:

    (注:一下图片采用自博客:http://www.cnblogs.com/Camilo/p/3917041.html,如果侵权请联系我删除)

    左子树左结点引起的不平衡:

    Node* LL(Node* node){
        Node* re=node->l;
        node->l=re->r;
        re->r=node;
        setHeight(node);    //注意:先进行这一步。因为node是re的子结点,从下往上调整
        setHeight(re);
        return re;
    }

    右子树右结点引起的不平衡:

    Node* RR(Node* node){
        Node* re=node->r;
        node->r=re->l;
        re->l=node;
        setHeight(node);
        setHeight(re);
        return re;
    }

    (注:编写技巧是在LL函数的基础上,把所有的r写成l,把所有的l写成r,轮换对称思想)

    左子树右结点引起的不平衡:

    Node* LR(Node* node){
        node->l=RR(node->l);
        node=LL(node);
        return node;
    }

    右子树左结点引起的不平衡:

    Node* RL(Node* node){
        node->r=LL(node->r);
        node=RR(node);
        return node;
    }

     

    第五步:在BST树的插入函数中编写平衡旋转代码:

    Node* insert(Node* p,int v){
        Node * node=new Node(v);
        if(!p){
            return node;
        }
        if(v < p->d){    //左子树 
            if(p->l){
                p->l=insert(p->l,v);
            }else{
                p->l=node;
            }
        }else{
            if(p->r){
                p->r=insert(p->r,v);
            }else{
                p->r=node;
            }
        }
        setHeight(p); 
        //平衡旋转代码 
        if(getHeight(p->l)-getHeight(p->r)==2){    //左子树不平衡 
            if(getHeight(p->l->l)>getHeight(p->l->r)){//左结点不平衡 
                p=LL(p);
            }else{        //右结点不平衡 
                p=LR(p);
            } 
        }
        if(getHeight(p->r)-getHeight(p->l)==2){    //右子树不平衡 
            if(getHeight(p->r->l)>getHeight(p->r->r)){//左结点不平衡 
                p=RL(p);
            }else{        //右结点不平衡 
                p=RR(p);
            } 
        }
        //end of 平衡旋转代码 
        return p;
    }

    打个OJ测试一下:1123. Is It a Complete AVL Tree

    AC代码:

    #include <stdio.h> 
    #include <queue> 
    #include <algorithm>
    
    using namespace std;
    
    typedef struct Node{
        int d;        //data
        int h=1;    //height
        struct Node* l=NULL;     
        struct Node* r=NULL; 
        Node(int d=0):d(d){
        }
    }Node; 
    
    int getHeight(Node* node){
        if(node) return node->h;    //如果非空返回这个结点的height 
        return 0;                  //空节点的高度是0 
    }
    
    void setHeight(Node* node){    //取左右子树高度的最大值,记得+1 
        node->h=max(getHeight(node->l),getHeight(node->r))+1;
    }
    
    Node* LL(Node* node){
        Node* re=node->l;
        node->l=re->r;
        re->r=node;
        setHeight(node);    //注意:先进行这一步。因为node是re的子结点,从下往上调整
        setHeight(re);
        return re;
    }
    
    Node* RR(Node* node){
        Node* re=node->r;
        node->r=re->l;
        re->l=node;
        setHeight(node);
        setHeight(re);
        return re;
    }
    
    Node* LR(Node* node){
        node->l=RR(node->l);
        node=LL(node);
        return node;
    }
    
    Node* RL(Node* node){
        node->r=LL(node->r);
        node=RR(node);
        return node;
    }
    
    Node* insert(Node* p,int v){
        Node * node=new Node(v);
        if(!p){
            return node;
        }
        if(v < p->d){    //左子树 
            if(p->l){
                p->l=insert(p->l,v);
            }else{
                p->l=node;
            }
        }else{
            if(p->r){
                p->r=insert(p->r,v);
            }else{
                p->r=node;
            }
        }
        setHeight(p); 
        //平衡旋转代码 
        if(getHeight(p->l)-getHeight(p->r)==2){    //左子树不平衡 
            if(getHeight(p->l->l)>getHeight(p->l->r)){//左结点不平衡 
                p=LL(p);
            }else{        //右结点不平衡 
                p=LR(p);
            } 
        }
        if(getHeight(p->r)-getHeight(p->l)==2){    //右子树不平衡 
            if(getHeight(p->r->l)>getHeight(p->r->r)){//左结点不平衡 
                p=RL(p);
            }else{        //右结点不平衡 
                p=RR(p);
            } 
        }
        //end of 平衡旋转代码 
        return p;
    }
    
    int cnt=0;
    
    int main(){
    //    freopen("I:\pat\树\AVL\1123_2.txt","r",stdin);
        int n,t;
        scanf("%d",&n);
        Node * root;
        for(int i=0;i<n;i++){
            scanf("%d",&t);
            root=insert(root,t);
        }
        queue<Node*> q;
        q.push(root);
        bool findNull=0;
        bool yes=1;
        bool after=0;
        while(!q.empty()){
            Node* t=q.front();
            q.pop();
            printf("%d",t->d);
            cnt++;
            if(cnt!=n)
                printf(" ");
            if(t->l){
                q.push(t->l);
                if(after) yes=0;
            }
            else after=1;
            if(t->r){
                q.push(t->r);
                if(after) yes=0;
            }
            else after=1;
        }
        puts("");
        puts(yes?"YES":"NO");
        return 0;
    }
  • 相关阅读:
    #ACsaber ——简单排序、字符串加空格、数组中的行 ~20.10.22
    #堆排序 20.09.27
    #并查集 20.09.25
    #卡特兰数 #抽屉原理 #Nim游戏 ——杂记
    #扩展欧几里得算法 ——线性同余方程 ~20.9.4
    #周测 7 —— 数的划分 、逆序对 、排座椅 、棋盘
    117. 占卜DIY
    116. 飞行员兄弟
    115.给树染色
    112.雷达设备
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8537110.html
Copyright © 2020-2023  润新知