zoukankan      html  css  js  c++  java
  • 二叉排序树第二版(平衡二叉树)

                 由于二叉排序树插入随意,毫无规则可言,自然时间效率就不能保证,极端情况下会退化成链表(左空右慢或反之)。

                 平衡二叉树就是在二叉排序树的基础上进行优化,平衡二叉树就是保证任何父节点的左右子树深度只能相差1、0、-1(左-右),所以每次插入一个新点都要修改这棵树使其平衡,学名叫旋转(其实不像旋转),这样效率就能达到log(n)。旋转的讲解 http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html 这里写很好, 不过代码有些问题。

                 附上完整代码,没有写成类模板。

                

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    
    using namespace std;
    typedef int type;
    const int BF=2;
    struct tree
    {
        type data;
        int h;  //深度
        int howmany; //  相等的记录
        tree *left,*right,*father;
    }*root;
    
    inline int max(int a,int b)
    {
        if(a>b) return a;
        else return b;
    }
    inline int height(tree *node)
    {
        if(node) return node->h;
        else return 0;
    }
    void initnode(tree *node)
    {
        node->h=0;
        node->howmany=1;
        node->left=NULL;
        node->right=NULL;
        node->father=NULL;
    }
    void changeNode(tree *s,tree *t)  //  son  temp;
    {
        if(s->father)
        {
            tree *r=s->father;
            if(r->left == s)
            {
                r->left = t;
                t->father = r;
            }
            else
            {
                r->right = t;
                t->father = r;
            }
        }
        else
        {
            root = t;
            t->father = NULL;
        }
        s->father=t;
    }
    void AdjustLeftLeft(tree *son)
    {
        tree *temp;
        temp = son->left;
        son->left = temp->right;
        if(temp->right) temp->right->father = son;
        temp->right = son;
    
        changeNode(son,temp);     //  更新父节点的指向
    
        int lh=height(son->left);
        int rh=height(son->right);
        son->h = lh > rh ? lh+1 : rh+1;  //  更新高度
        lh=height(temp->left);
        temp->h = lh > son->h ? lh+1 : son->h+1;
    }
    void AdjustRightRight(tree *son)
    {
        tree *temp;
        temp = son->right;
        son->right = temp->left;
        if(temp->left) temp->left->father = son;
        temp->left = son;
    
        changeNode(son,temp);
    
        int lh=height(son->left);             //  和上面是雷同代码   可以写成函数
        int rh=height(son->right);
        son->h = lh > rh ? lh+1 : rh+1;  //  更新高度
        lh=height(temp->left);
        temp->h = lh > son->h ? lh+1 : son->h+1;
    }
    void AdjustLeftRight(tree *son)
    {
        AdjustRightRight(son->left);
        AdjustLeftLeft(son);
    }
    void AdjustRightLeft(tree *son)
    {
        AdjustLeftLeft(son->right);
        AdjustRightRight(son);
    }
    void insertnode(tree *&node,const type x,tree *f)   //   这里传引用,  空指针实参传过来无用
    {
        if(node==NULL)
        {
            node=new tree;
            if(node == NULL)
            {
                cout<<"no  memery!"<<endl;
                exit(0);
            }
            node->data=x;
            initnode(node);
            node->father=f;
        }
        else if(node->data > x)  // 放在左子树
        {
            insertnode(node->left,x,node);
            if(height(node->left) -height(node->right) == BF)   //  这如果不写成函数  就容易报空指针异常! 学着点
            {
                if(node->left->data > x)
                    AdjustLeftLeft(node);
                else
                    AdjustLeftRight(node);
            }
        }
        else if(node->data < x)
        {
            insertnode(node->right,x,node);
            if(height(node->right) - height(node->left) == BF)
            {
                if(node->right->data < x)
                    AdjustRightRight(node);
                else
                    AdjustRightLeft(node);
            }
        }
        else if(node->data == x) node->howmany++;
        int i,j;
        if(node->left == NULL) i=0;
        else i=node->left->h;
        if(node->right == NULL) j=0;
        else j=node->right->h;
        node->h = max(i,j)+1;
    }
    void midorder(tree *r)
    {
        if(r->left) midorder(r->left);
        for(int i=1;i<=r->howmany;i++)
            cout<<r->data<<" ";
        if(r->right) midorder(r->right);
    }
    void DeleteAll(tree *node)
    {
        if(node->right) DeleteAll(node->right);
        if(node->left) DeleteAll(node->left);
        delete node;
    }
    void DeleteNode(tree *node,type x)
    {
        if(node == NULL)
        {
            printf("无此点 
    ");
            return;
        }
        else if(x > node->data)    //  删除右子树中的节点,如果需要平衡只可能是左左或左右这两种情况
        {
            DeleteNode(node->right,x);
            if(height(node->right) - height(node->left) == BF)
            {
                if(height(node->left->left) > height(node->left->right))  //  这需要判空吗?  应该不用
                    AdjustLeftLeft(node);
                else
                    AdjustLeftRight(node);
            }
        }
        else if(x < node->data)
        {
            DeleteNode(node->left,x);
            if(height(node->left) - height(node->right) == BF)
            {
                if(height(node->right->right) > height(node->right->left))
                    AdjustRightRight(node);
                else
                    AdjustRightLeft(node);
            }
        }
        else
        {
            tree *temp1,*temp2;
            if(node->howmany > 1)   //  如果这个数不是一个  什么都不用干 删次数就好了
            {
                node->howmany--;
                return;
            }
            else if(node->left && node->right)   //  删除的点有两个儿子
            {
                temp1 = node->right;
                while(temp1->left)
                {
                    int h1=height(temp1->left)-1;
                    int h2=height(temp1->right);
                    temp1->h = h1>h2 ? h1:h2; //  拿出节点就要更新高度
                    temp1 = temp1->left;  //  找到右子树最小值 准备替换。
                }
                node->data=temp1->data;
                temp2 = temp1->father;
                temp2->left=NULL;
                delete temp1;
                if(height(node->left) - height(node->right) == BF)
                {
                    if(height(node->left->left) > height(node->left->right))
                        AdjustLeftLeft(node);
                    else
                        AdjustLeftRight(node);
                }
                //  没落什么吧
            }
            else    //  0或1个儿子
            {
                if(node->howmany > 1)
                {
                    node->howmany--;
                    return ;
                }
                else
                {
                    if(node->left) temp1=node->left;
                    else temp1=node->right;
                    if(temp1)
                    {
                        node->data = temp1->data;
                        node->h--;
                        node->left = node->right = NULL;
                        delete temp1;
                    }
                    else
                    {
                        temp2 = node->father;
                        if(temp2->left == node) temp2->left = NULL;
                        else temp2->right = NULL;
                        delete node;
                    }
                    return ;
                }
            }
            int hl = height(node->left);   //  回朔的节点全部更新一下高度
            int hr = height(node->right);
            node->h = hr>hl ? hr:hl;
        }
    }
    bool searchnode(tree *node,type x)   //  查找
    {
        if(node->data == x)
        {
            return true;
        }
        else if(node->data > x)
        {
            return searchnode(node->left,x);
        }
        else
        {
            return searchnode(node->right,x);
        }
    } 
    int main()
    {
        int n;
        scanf("%d",&n);
        while(n--)
        {
            int a;
            scanf("%d",&a);
            insertnode(root,a,NULL);
        }
        midorder(root);
        cout<<endl;
        DeleteNode(root,5);
        midorder(root);
        DeleteAll(root);
        return 0;
    }
    
    /*
    10
    8 4 5 7 6 9 2 1 3 0
    */
  • 相关阅读:
    如何申请iOS开发者证书/发布app到手机
    STL
    TCP/IP编程
    STL
    STL
    Python网络爬虫
    Python网络爬虫
    Python网络爬虫
    Python编程-基础知识-python项目包和文件的管理以及如何引用相对路径的包和模块
    带你认识HL7和CDA
  • 原文地址:https://www.cnblogs.com/liboyan/p/4940637.html
Copyright © 2011-2022 走看看