• 平衡二叉树(AVL树)学习


    学了平衡树有一段时间了,一直想来总结一下,就今天吧,用最简单的图和代码来说明白

    平衡树的基本操作:

    LL型平衡旋转:

    void LL(node *&a){
        b = a->lch;
        a->lch = b->rch;
        b->rch = a;
        a->bf = b->bf = 0;
    }

    RR型平衡旋转:

    void RR(node *&a){
        b = a->lch;
        a->rch = b->lch;
        b->lch = a;
        a->bf = b->bf = 0;
    }

    LR型平衡旋转:

    void LR(node *&a){
        node *c = NULL;
        b = a->lch;
        c = b->rch;
        a->lch = c->rch;
        b->rch = c->lch;
        c->rch = a;
        c->lch = b;
        switch (c->bf)
        {
        case 1: {a->bf = -1; b->bf = 0break;}
        case -1: {a->bf = 0; b->bf = 1break;}
        case 0:{a->bf = b->bf = 0 ; break;}
        }
        c->bf = 0;
        b = c; //把b调整成已平衡的子根
    }

    RL型平衡旋转:

    void RL(node *&a){
        node *c = NULL;
        b = a->rch;
        c = b->lch;
        a->rch = c->lch;
        b->lch = c->rch;
        c->lch = a;
        c->rch = b;
        switch (c->bf)
        {
        case 1:{a->bf = 0; b->bf = -1break;}
        case -1:{a->bf = 1; b->bf = 0break;}
        case 0:{a->bf = b->bf = 0break;}
        }
        c->bf =0;
        b = c;
    }

    完整代码如下:

    #include<cstdio>
    using  namespace std;
    
    struct node{
        int bf,key;
        node *lch,*rch;
    };
    
    node *bst = NULL,*b = NULL;
    int n;
    
    void LL(node *&a){
        b = a->lch;
        a->lch = b->rch;
        b->rch = a;
        a->bf = b->bf = 0;
    }
    
    void RR(node *&a){
        b = a->lch;
        a->rch = b->lch;
        b->lch = a;
        a->bf = b->bf = 0;
    }
    
    void LR(node *&a){
        node *c = NULL;
        b = a->lch;
        c = b->rch;
        a->lch = c->rch;
        b->rch = c->lch;
        c->rch = a;
        c->lch = b;
        switch (c->bf)
        {
        case 1: {a->bf = -1; b->bf = 0break;}
        case -1: {a->bf = 0; b->bf = 1break;}
        case 0:{a->bf = b->bf = 0 ; break;}
        }
        c->bf = 0;
        b = c; //把b调整成已平衡的子根
    }
    
    void RL(node *&a){
        node *c = NULL;
        b = a->rch;
        c = b->lch;
        a->rch = c->lch;
        b->lch = c->rch;
        c->lch = a;
        c->rch = b;
        switch (c->bf)
        {
        case 1:{a->bf = 0; b->bf = -1break;}
        case -1:{a->bf = 1; b->bf = 0break;}
        case 0:{a->bf = b->bf = 0break;}
        }
        c->bf =0;
        b = c;
    }
    
    void Insert(node *&t, int k){
        node *s = NULL,*f = NULL, *p = NULL,*q = NULL, *a = NULL;
        int d = 0;;
        bool balanced = true;
        s new node;
        s->lch = s->rch = NULL;
        s->bf =  0;
        s->key = k;
        if(t == NULL) t = s;
        else {   //在以节点t为根的平衡树上插入关键字等于k的新节点s
           
            a = p = t;
            while(p!= NULL){    //找到插入位置q
                if(p->bf!=0) {a = p; f = q;}
                q = p;
                if(s->key < p->key) p=p->lch;
                else p = p->rch;
            }
            if(s->key < q->key) q->lch = s;
            else q->rch = s;
    
            //修改a-s路径上的各节点的平衡因子值
            if(s->key < a->key)
            {p = a->lch; b = p; d = 1;}
            else 
            {p = a->rch; b = p; d = -1;}
    
            while(p!=s){
                if(s->key < p->key)
                {p->bf = 1; p= p->lch;}
                else
                {p->bf = -1; p=p->rch;}
            //判断a的子树是否失去平衡
            balanced = true;
            if(a->bf == 0) a->bf = d;
            else if(a->bf == -d) a->bf = 0;
                 else {  //失去平衡,判别旋转类型
                    balanced = false;
                    if(d == 1){
                        switch (b->bf)
                        {
                        case 1:{LL(a); break;}
                        case -1:{LR(a); break;}
                        }
                    }
                    else {
                        switch (b->bf)
                        {
                        case -1:{RR(a); break;}
                        case 1:{RL(a); break;}
                        }
                    }
                 }
                 if(!balanced)  //在RL和LR处理旋转结束时令b = c
                    if(f == NULL) t = b;
                    else if(f->lch == a) f->lch = b;
                    else if(f->rch == a) f->rch = b;
         }
        }
    }
    
    void out(node *root){
        printf("(");
        if(root->lch != NULL) out(root->lch);
        printf("%d",root->key);
        if(root->rch != NULL) out(root->rch);
        printf(")");
    }
    
    int main(){
        printf("input data(if < 0 then over!):
    ");
        do{
            scanf("%d",&n);
            if(n >=0) Insert(bst,n);
        }while(n >=0);
        printf("output sorted data
    ");
        out(bst);
        return 0;
    }
  • 相关阅读:
    实用分页小方法
    Android:Handler实现异步处理功能
    Android--sharepreference总结
    安卓 如何向数据库传值
    Activity 之间的传值
    Android 双击返回键退出程序 实现
    HttpUtitlity.UrlEncode
    android 如何设置背景的透明度
    比较Date时间先后
    iOS 判断字符串中含有某个字符串 rangeOfString
  • 原文地址:https://www.cnblogs.com/wxx23-IOU/p/13586459.html
Copyright © 2020-2023  润新知