一步一步编写AVL树

送分小仙女□ 提交于 2020-01-24 06:57:31

第一步:定义结构体

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;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!