二叉平衡树

平衡二叉树(AVL 树)

1.平衡二叉树的定义

  平衡二叉树任然是一棵二叉查找树,所谓平衡是指,对 AVL 树的任意结点来说,其左子树与右子树的高度之差的绝对值不超过 1,其中左子树与右子树的高度之差称为该节点的平衡因子
  

  由于需要对每个结点都得到平衡因子,因此需要在树的结构中加入一个变量 height 来记录以当前为根结点的子树的高度:


    struct node{
        int v,height;   //v 为权值,height 为当前子树高度
        node* lchild;
        node* rchild;
    };

  在这种定义下,如果需要新建一个结点,就可以采用如下写法:


    node* newNode(int v){
        node* Node = new node;

        Node->v = v;
        Node->height = 1;   //结点初始高度为 1
        Node->lchild = Node->rchild = NULL;

        return Node;
    }

  可以根据下面的函数获取结点 root 所在子树的当前高度:


    int getHeight(node* root){
        if(root == NULL) return 0;  //空结点高度为 0

        return root->height;
    }

  根据定义,可以通过下面的函数计算平衡因子:


    int getBalanceFactor(node* root){
        //左子树高度减右子树高度
        return getHeight(root->lchild) - getHeight(root->rchild);
    }

  显然结点 root 所在子树的 height 等于其左子树的 height 与右子树的 height 的较大值加 1,因此可以通过下面的函数来更新 height:


    void updateHeight(node* root){
        //结点 root 的高度等于左子树和右子树高度的最大值加 1
        root->height = max(getHeight(root->lchild),getHeight(root->rchild)) + 1;
    }

2.平衡二叉树的基本操作

1. 查找操作

  由于平衡二叉树是一棵二叉查找树,因此其查找操作与二叉查找树相同。


    void search(node* root,int x){          //查找权值为 x 的结点
        if(root == NULL){
            cout<<"查找失败!"<<endl;
            return;
        }
        if(x == root->data){
            cout<<root->data<<endl;
        }else if(x < root->data){
            search(root->lchild,x);
        }else{
            search(root->rchild,x);
        }
    }

2.插入操作

  • 左旋:

    //左旋(Left Rotation)
    void LR(node* &root){

        if(root->rchild != NULL){
            node* temp = root->rchild;
            root->rchild = temp->lchild;
            temp->lchild = root;
            updateHeight(root);
            updateHeight(temp);
            root = temp;
        }
    }
  • 右旋:

    //右旋(Right Rotation)
    void RR(node* &root){

        if(root->lchild != NULL){
            node* temp = root->lchild;
            root->lchild = temp->rchild;
            temp->rchild = root;
            updateHeight(root);
            updateHeight(temp);
            root = temp;
        }
    }

AVL树的插入分为 LL型、LR型、RR型、RL型:

  在这个基础上,由于需要插入的结点开始从下往上判断结点是否失衡,因此需要在每个 insert 函数之后更新当前子树的高度,并在这之后根据树型是 LL 型、LR型、RR型、RL型之一来进行平衡操作:


    //插入权值为 v 的结点
    void insert(node* &root,int v){
        if(root == NULL){         //到达空结点
            root = newNode(v);
            return;
        }
        if(v < root->v){
            insert(root->lchild,v);
            updateHeight(root); //更新树高
            if(getBalanceFactor(root) == 2){
                if(getBalanceFactor(root->lchild) == 1)//LL型
                    RR(root);
                else if(getBalanceFactor(root->lchild) == -1){//LR
                    LR(root->lchild);
                    RR(root);
                }
            }
        }
        else {
                insert(root->rchild,v);
                updateHeight(root);
                if(getBalanceFactor(root) == -2){
                    if(getBalanceFactor(root->rchild) == -1){//RR
                        LR(root);
                    }else if(getBalanceFactor(root->rchild) == 1){//RL
                        RR(root->rchild);
                        LR(root);
                    }
                }
            }
    }

3.AVL 树的建立


    node* create(int data[],int n){

        node* root = NULL;      //新建空结点
        for(int i = 0;i < n;i++){
            insert(root,data[i]);   //将 data[0]-data[n-1] 插入 AVL 树
        }
        return root;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值