• avl树的操作证明


      以下用大O表示节点,ABC表示三个集合。

      仅分析左子树的情况,因为对称,右子树的情况一样。

      插入节点前

          O

         /    

        O        A

         /    

          B       C

      插入节点后:

          O

         /    

        O        A

         /    

          B       C

        /

      O

          此时造成了最高节点的不平衡,说明了B+2 - A = 2;另外可以知道B = C,考虑B<C,那么在插入节点前最高点就已经不平衡了,考虑B > C,那么最高的左子树就已经不平衡了,而不应该考虑最高点。所以此时可以知道A = B = C。

      左子树单旋转之后:

          O

         /    

        B        O

         /          /    

          O         C       A

      对于最高点来说,左子树深度为B+1,右子树深度为A+1,即B + 1。

      对比插入后的树,可以知道只有原最高节点的深度发生变化,所以只需更新该节点的深度。

    另外一种情况:

    插入后:

     

          O

         /    

        O        A

         /    

          B       C 

                 /

              O

    此时如果单旋转,结果为:

          O

         /    

        B        O

                     /    

                      C       A

                    /

                  O

    明显这个情况并没有得到解决。

    所以首先要单右旋转最高节点的左子树,结果为:

          O

         /    

        C        A

         /    

          O       O

         /

       B

    此时可以知道C集合的深度发生了变化,需要更新C的深度,而之前更新的是最高点的深度,所以在旋转时需要更新原最高点和现最高点的深度。

    第二次左旋转原最高点,结果为

          C

         /    

        O        O

         /         /    

          B        O       A

    这里面的正确有一些缺陷,应该把ABC集合多展开几层,否则在双旋转时的证明有些怪异,反正就是这个思路,因为画图实在是太麻烦了。

    最后是代码:

      

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    typedef struct _node
    {
        int element;
        int high;
        struct _node *lefttree;
        struct _node *righttree;
    }node;
    
    int gethigh(node *t)
    {
        if(t == 0)
            return -1;
        return t->high;
    }
    
    node *singlerotatewithleft(node *t)
    {
        node *tmp = t->lefttree;
        t->lefttree = tmp->righttree;
        tmp->righttree = t;
    
        tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + 1;
        t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1;
        return tmp;
    }
    
    node *singlerotatewithright(node *t)
    {
        node *tmp = t->righttree;
        t->righttree = tmp->lefttree;
        tmp->lefttree = t;
    
        tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + 1;
        t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1;
        return tmp;
    }
    
    node *doubleroratewithleft(node *t)
    {
        t->lefttree = singlerotatewithright(t->lefttree);
        return singlerotatewithleft(t);
    }
    
    node *doubleroratewithright(node *t)
    {
        t->righttree = singlerotatewithleft(t->righttree);
        return singlerotatewithright(t);
    }
    
    node *insert(node *t,int element)
    {
        if (t == 0)
        {
            t = (node *)malloc(sizeof(node));
            t->element = element;
            t->lefttree = t->righttree = 0;
        }
        else if(t->element > element){
            t->lefttree = insert(t->lefttree,element);
            if(gethigh(t->lefttree) - gethigh(t->righttree) == 2)
                if(element < t->lefttree->element)
                    t= singlerotatewithleft(t);
                else
                    t= doubleroratewithleft(t);
        }
        else if(t->element < element){
            t->righttree = insert(t->righttree,element);
            if(gethigh(t->righttree) - gethigh(t->lefttree) == 2)
                if(element > t->righttree->element)
                    t= singlerotatewithright(t);
                else
                    t= doubleroratewithright(t);
    
        }
        t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1;
        return t;
    }
    
    node *find(node *t,int element)
    {
        if(t == 0)
            return 0;
        else if(t->element > element)
            return find(t->lefttree,element);
        else if(t->element < element)
            return find(t->righttree,element);
        else
            return t;
    }
    
    node* findmin(node *t)
    {
        if(t == 0)
            return 0;
        if(t->lefttree == 0)
            return t;
        else
            return findmin(t->lefttree);
    }
    
    node *delele(node *t,int element)
    {
        if(t == 0)
            return 0;
        else if(t->element > element)
            t->lefttree = delele(t->lefttree,element);
        else if(t->element < element)
            t->righttree = delele(t->righttree,element);
        else
        {
            if(t->lefttree && t->righttree)
            {
                node *tmp;
                tmp = findmin(t->righttree);
                t->element = tmp->element;
                t->righttree = delele(t->righttree,tmp->element);
            }
            else
            {
                node *tmp;
                tmp = t->lefttree?t->lefttree:t->righttree;
                free(t);
                t = tmp;
            }
        }
        return t;
    }
    
    void printtree(node *t)
    {
        if(t == 0)
            return;
        printtree(t->lefttree);
        printf("%d	",t->element);
        printf("high = %d
    ",t->high);
        printtree(t->righttree);
    }
    
    int main()
    {
        int a[10] = {1,2,3,4,5,6,7,8,9};
        node *t;
        int i = 1;
        t = insert(0,1);
        for(;i<7;i++){
            t = insert(t,a[i]);
            //printtree(t);
            //sleep(1);
        }
            //t = delele(t,6);
        printtree(t);
        printf("
    ");
        //while(1);
        return 0;
    }

     

                

     

     

  • 相关阅读:
    shell 逻辑操作符
    shell 整数
    shell 字符串
    常用文件测试操作符
    系统级脚本 rpcbind
    shell 特殊字符
    redhat7.5 升级OpenSSH_7.8p1
    kubernetes 项目
    salt 安装kubernetes集群3节点
    web应用
  • 原文地址:https://www.cnblogs.com/leo0000/p/5671513.html
Copyright © 2020-2023  润新知