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

             平衡二叉树就是在二叉排序树的基础上进行优化,平衡二叉树就是保证任何父节点的左右子树深度只能相差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("无此点 \n");
        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
*/

 

posted on 2015-11-05 20:03  潜伏的大青蛙  阅读(215)  评论(0编辑  收藏  举报