• AVL树模板


      AVL树也是一种搜索二叉树(BST),即左孩纸比父节点小,右孩纸比父节点大。AVL树的插入就是通过遍历找到合适的位置插入,插入后可能会导致高度差大于1,所以需要通过旋转操作进行自平衡。AVL树的删除,找到删除节点,然后找到其子节点下最接近该节点val值的叶子节点,然后把该节点的val赋值为叶子节点的val,然后就转换成删除该节点下某一叶子节点了。最后进行自平衡调整。比如一个二叉树。

            5

           3           6

         1          4             7

      0     2

    (5的左右节点3,6),3的左右节点是(1,4),1的左右节点是(0,2)

    ,准备删除3,找到3节点的位置,然后从3的孩纸节点中找到最接近他的叶子节点(2),然后把3节点的值改成2

            5

           2           6

         1          4             7

      0     2

     然后题目就变成删除val为2的节点了。

      花了半天时间学习AVL树,AVL树只要有LL,RR,LR,RL四种旋转操作,动态增加与减少都需要四种操作结合。AVL树比普通二叉树的结构体多了一个高度,用于保证左右子节点高度差小于2。在计算高度的时候,最好自己写一个函数,因为要判断是否为NULL,NULL则表示为0。如果用指针去取高度,为NULL的时候会报错。并且在计算高度差的时候,要注意是左节点减去右节点还是右节点减去左节点。

      主要灵感来源于:http://blog.csdn.net/whucyl/article/details/17289841

      

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct Node
    {
        int val;
        int height;
        Node* left;
        Node* right;
        Node()
        {
            height = 1;
            left = NULL;
            right = NULL;
        }
        //更新高度
        void UpdateHeight()
        {
            int leftheight = left ? left->height : 0;
            int rightheight = right ? right->height : 0;
            height = max(leftheight,rightheight)+1;
        }
        //左右子孩子高度差
        int DisHeight()
        {
            int leftheight = left ? left->height : 0;
            int rightheight = right ? right->height : 0;
            return leftheight-rightheight;
        }
    };
    
    Node* LL(Node* anode)
    {
        Node* bnode = anode->left;
        Node* cnode = bnode->right;
        bnode->right = anode;
        anode->left = cnode;
        //更新高度时,anode一定要先更新
        anode->UpdateHeight();
        bnode->UpdateHeight();
        return bnode;
    }
    
    Node* RR(Node* anode)
    {
        Node* bnode = anode->right;
        Node* cnode = bnode->left;
        bnode->left = anode;
        anode->right = cnode;
        anode->UpdateHeight();
        bnode->UpdateHeight();
        return bnode;
    }
    
    Node* LR(Node* anode)
    {
        anode->left = RR(anode->left);
        return LL(anode);
    }
    
    Node* RL(Node* anode)
    {
        anode->right = LL(anode->right);
        return RR(anode);
    }
    
    Node* Insert(Node* node,int val)
    {
        if(node == NULL)
        {
            node = new Node();
            node->val = val;
        }
        else if(val > node->val)
        {
            node->right = Insert(node->right,val);
            int disH = node->DisHeight();
            if(disH == -2)
            {
                if(val > node->right->val) node = RR(node);
                else node = RL(node);
            }
        }
        else if(val < node->val)
        {
            node->left = Insert(node->left,val);
            int disH = node->DisHeight();
            if(disH == 2)
            {
                if(val < node->left->val) node = LL(node);
                else node = LR(node);
            }
        }
        node->UpdateHeight();
        return node;
    }
    
    Node* Delete(Node* node,int val)
    {
        if(node == NULL){return NULL;}
        else if(node->val < val)
        {
            node->right = Delete(node->right,val);
        }
        else if(node->val > val)
        {
            node->left = Delete(node->left,val);
        }
        else
        {
            if(node->left)
            {
                Node* nd;
                for(nd=node->left;nd->right != NULL;nd = nd->right);
                node->val = nd->val;
                node->left = Delete(node->left,nd->val);
            }
            else if(node->right)
            {
                Node* nd;
                for(nd=node->right;nd->left != NULL;nd = nd->left);
                node->val = nd->val;
                node->right = Delete(node->right,nd->val);
            }
            else
            {
                delete node;
                return NULL;
            }
        }
    
        if(node->DisHeight()==2)
        {
            if(node->left->DisHeight()==1)
                node = LL(node);
            else node = LR(node);
        }
        else if(node->DisHeight()==-2)
        {
            if(node->right->DisHeight()==-1)
                node = RR(node);
            else node = RL(node);
        }
    
        node->UpdateHeight();
        return node;
    }
    
    void pre_travel(Node* node)
    {
        if(node==NULL) return;
        printf("%d ",node->val);
        pre_travel(node->left);
        pre_travel(node->right);
    }
    void in_travel(Node* node)
    {
        if(node==NULL) return;
        in_travel(node->left);
        printf("%d ",node->val);
        in_travel(node->right);
    }
    
    int main()
    {
        //test code
        Node *root = NULL;
        root = Insert(root,5);
        root = Insert(root,6);
        root = Insert(root,3);
        root = Insert(root,2);
        root = Insert(root,4);
        root = Insert(root,1);
        root = Insert(root,9);
        root = Insert(root,8);
        root = Insert(root,7);
    
        printf("先序遍历:
    ");
        pre_travel(root);
        printf("
    ");
        printf("中序遍历:
    ");
        in_travel(root);
        printf("
    ");
    
        root = Delete(root,6);
        root = Delete(root,1);
        printf("
    先序遍历:
    ");
        pre_travel(root);
        printf("
    ");
        printf("中序遍历:
    ");
        in_travel(root);
        printf("
    ");
        return 0;
    }

    PAT1066,简单AVL的插入操作。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    struct Node
    {
        int val;
        int H;
        Node* left;
        Node* right;
        Node()
        {
            H = 1;
            left = NULL;
            right = NULL;
        }
        int LH(){return left?left->H:0;}
        int RH(){return right?right->H:0;}
        void UpdateH(){H = max(LH(),RH())+1;}
        int DisH(){return LH() - RH();}
    };
    
    Node* LL(Node* anode)
    {
        Node *bnode = anode->left;
        Node *cnode = bnode->right;
        bnode->right = anode;
        anode->left = cnode;
        anode->UpdateH();
        bnode->UpdateH();
        return bnode;
    }
    
    Node* RR(Node* anode)
    {
        Node *bnode = anode->right;
        Node *cnode = bnode->left;
        bnode->left = anode;
        anode->right = cnode;
        anode->UpdateH();
        bnode->UpdateH();
        return bnode;
    }
    
    Node* LR(Node* anode)
    {
        anode->left = RR(anode->left);
        return LL(anode);
    }
    
    Node* RL(Node* anode)
    {
        anode->right = LL(anode->right);
        return RR(anode);
    }
    
    Node* Insert(Node* node,int val)
    {
        if(node==NULL)
        {
            node = new Node();
            node->val = val;
        }
        else if(val > node->val)
        {
            node->right = Insert(node->right,val);
            if(node->DisH()==-2)
            {
                if(val > node->right->val) node = RR(node);
                else node = RL(node);
            }
        }
        else if(val < node->val)
        {
            node->left = Insert(node->left,val);
            if(node->DisH()==2)
            {
                if(val < node->left->val) node = LL(node);
                else node = LR(node);
            }
        }
    
        node->UpdateH();
        return node;
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        Node* root = NULL;
        for(int i=0;i<n;++i)
        {
            int val;
            scanf("%d",&val);
            root = Insert(root,val);
        }
        printf("%d
    ",root->val);
        return 0;
    }
    View Code

    PAT1123,简单AVL的插入与已知广度遍历与宽度遍历的关系

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n;
    
    struct Node
    {
        int val;
        int H;
        Node* left;
        Node* right;
        Node()
        {
            H = 1;
            left = NULL;
            right = NULL;
        }
        int LH(){return left?left->H:0;}
        int RH(){return right?right->H:0;}
        void UpdateH(){H = max(LH(),RH())+1;}
        int DisH(){return LH()-RH();}
    };
    
    Node* LL(Node* anode)
    {
        Node* bnode = anode->left;
        Node* cnode = bnode->right;
        bnode->right = anode;
        anode->left = cnode;
        anode->UpdateH();
        bnode->UpdateH();
        return bnode;
    }
    Node* RR(Node* anode)
    {
        Node* bnode = anode->right;
        Node* cnode = bnode->left;
        bnode->left = anode;
        anode->right = cnode;
        anode->UpdateH();
        bnode->UpdateH();
        return bnode;
    }
    
    Node* LR(Node* anode)
    {
        anode->left = RR(anode->left);
        return LL(anode);
    }
    
    Node* RL(Node* anode)
    {
        anode->right = LL(anode->right);
        return RR(anode);
    }
    
    Node* Insert(Node* node,int val)
    {
        if(node==NULL)
        {
            node = new Node();
            node->val = val;
        }
        else if(val < node->val)
        {
            node->left = Insert(node->left,val);
            if(node->DisH()==2)
            {
                if(val < node->left->val) node=LL(node);
                else node=LR(node);
            }
        }
        else if(val > node->val)
        {
            node->right = Insert(node->right,val);
            if(node->DisH()==-2)
            {
                if(val > node->right->val) node=RR(node);
                else node=RL(node);
            }
        }
        node->UpdateH();
        return node;
    }
    
    vector<int> vi;
    void bfs(Node* node)
    {
        queue<Node*> qn;
        qn.push(node);
        bool bFirst = true;
        while(!qn.empty())
        {
            Node* temp = qn.front();
            qn.pop();
            if(temp->left){qn.push(temp->left);}
            if(temp->right){qn.push(temp->right);}
            if(bFirst) bFirst = false;
            else printf(" ");
            printf("%d",temp->val);
            vi.push_back(temp->val);
        }
        printf("
    ");
    }
    
    int Index = 0;
    int a[30],b[30];
    
    void Travel(Node* node)
    {
        if(node == NULL) return;
        Travel(node->left);
        b[Index++] = node->val;
        Travel(node->right);
    }
    
    void Travel2(int k)
    {
        if(k >= n) return;
        Travel2(2*k+1);
        a[k] = b[Index++];
        Travel2(2*k+2);
    }
    
    int main()
    {
        scanf("%d",&n);
        Node *root = NULL;
        for(int i=0;i<n;++i)
        {
            int val;
            scanf("%d",&val);
            root = Insert(root,val);
        }
        bfs(root);
        Travel(root);
        Index = 0;
        Travel2(0);
        bool bOK = true;
        for(int i=0;i<n;++i)
            if(a[i] != vi[i]){bOK = false;break;}
        if(bOK) printf("YES
    ");
        else printf("NO
    ");
        return 0;
    }
    View Code

     思考题:已知AVL数的插入顺序,求根节点值(有没有简单的方法)?

  • 相关阅读:
    Nginx错误日志配置信息详解
    CentOS 7 开放防火墙端口
    Windows Server 2008 R2常规安全设置及基本安全策略
    Whitewidow:SQL 漏洞自动扫描工具
    Windows Server 2008 架设 Web 服务器教程(图文详解)
    如何修改windows系统远程桌面默认端口
    Nginx的访问日志配置信息详解
    重构手法之在对象之间搬移特性【2】
    重构手法之在对象之间搬移特性【1】
    重构手法之重新组织函数【5】
  • 原文地址:https://www.cnblogs.com/jlyg/p/7521434.html
Copyright © 2020-2023  润新知