平衡二叉树

#include <iostream>
#include <stdlib.h>
#include <stack>
using namespace std;

template<typename Type>
struct VALNode
{
    int bf;
    Type data;
    struct VALNode *left;
    struct VALNode *right;
    VALNode(Type d= Type()):bf(0),data(d),left(NULL),right(NULL){}
};

template<typename Type>
class VALTree
{
public:
    VALTree():root(NULL){}
    bool Insert(Type ar[],int n)
    {
        for(int i=0;i<n;i++)
        {
            Insert(root,ar[i]);
        }
        return true;
    }
    bool Insert(VALNode<Type> *&ptr,Type val)
    {
        VALNode<Type> *p = ptr;
        VALNode<Type> *q = NULL;
        VALNode<Type> *pr = NULL;
        int d;
        stack<VALNode<Type>* > st;
        while(p!=NULL)
        {
            if(p->data == val)return false;
            pr=p;
            st.push(pr);
            if(p->data>val)p=p->left;
            else p=p->right;
        }
        p = new VALNode<Type>(val);
        if(p==NULL){cout<<"no memory!!!"<<endl;exit(0);}
        if(pr==NULL)
            {ptr = p;return true;}
        else
        {
            if(pr->data>val)pr->left=p;
            else pr->right=p;
        }
        while(st.empty()!=true)
        {
            pr = st.top();
            st.pop();
            if(pr->data>p->data)
                pr->bf--;
            else pr->bf++;

            if(pr->bf==0)break;
            if(pr->bf == 1 || pr->bf == -1)
                p = pr;
            else
            {
                    d = (pr->bf<0)?-1:1;//标记位判断需要旋转的形状.
                    if(p->bf==d)//判断是 / 或者 \ 类型。
                        {
                            if(p->bf==-1)
                                RotateR(pr);//右旋转.
                            else
                                RotateL(pr);
                        }
                    else//这里是 < 或者 > 类型。
                        {
                            if(d==-1)//  <
                                {
                                p=p->right;//这个地方不能少,没有这句时,我开始怎么调试都不对,因为我做了LR两次翻转,所以根(翻转)节点会变.
                                RotateLR(pr);
                                }
                            else
                                RotateRL(pr);
                        }                   
            }
        }
        if(st.empty()==true)ptr=pr;
        else//链接
        {
            q = st.top();//ptr 还有父亲节点,这就需要将旋转的结果链接起来.
            if(q->left==q)
                    q->left = p;
            else 
                    q->right = p;
        }
        return true;
    }   
private:
    void RotateLR(VALNode<Type> *&ptr)
    {
        VALNode<Type> *p = ptr;
        VALNode<Type> *q = p->left;
        ptr = q->right;

        q->right = ptr->left;
        ptr->left = q;
        if(ptr->bf<=0)q->bf=0;
        else q->bf = -1;
        p->left = ptr->right;
        ptr->right = p;
        if(ptr->bf==-1)p->bf=1;
        else p->bf=0;
    }
    void RotateRL(VALNode<Type> *&ptr)
    {
        VALNode<Type> *p = ptr;
        VALNode<Type> *q = p->right;
        ptr = q->left;

    q->left = ptr->right;
        ptr->right = q;
        if(ptr->bf>=0)q->bf=0;
        else q->bf=1;

        p->right = ptr->left;
        ptr->left = p;
        if(ptr->bf==1)q->bf=-1;
        else q->bf=0;
        ptr->bf=0;

    }
    void RotateL(VALNode<Type> *&ptr)
    {
        VALNode<Type> *p = ptr->right;
        ptr -> right = p->left;
        p->left = ptr;
        p->bf = ptr->bf = 0;        
    }
    void RotateR(VALNode<Type> *&ptr)
    {
        VALNode<Type> *p = ptr->left;//保存ptr的左节点p。
        ptr->left = p->right;
//截肢ptr左肢,并且将p的右节点挂到ptr左肢。
        p->right = ptr;
        p->bf = ptr->bf = 0;
//将ptr挂载p的右肢上面,当然做到这一步还没有完成,如果ptr还有父节点呢?所以就需要我们在外面链接。
    }   
    public:
    void Remove(Type val)
    {
        Remove(root,val);
    }
    private:
    bool Remove(VALNode<Type> *&ptr,Type val)
    {
        VALNode<Type> *pr = NULL,*p=ptr,*q,*ppr;int d,dd=0;
        stack<VALNode<Type> *>st;
        while(p!=NULL)  
        {
            if(val == p->data)break;
            pr=p;
            st.push(pr);
            if(val<p->data)p=p->left;
            else p=p->right;
        }
        if(p==NULL)return false;
        if(p->left!=NULL && p->right!=NULL)
        {
            pr=p;
            st.push(pr);
            q=p->left;
            while(q->right!=NULL)
                {
                    pr=q;
                    st.push(pr);
                    q=q->right;
                }
            p->data = q->data;
            p=q;
        }
        if(p->left!=NULL)q=p->left;
        else q=p->right;
        if(pr==NULL)ptr=q;
        else
        {
            if(pr->left==p)pr->left=q;
            else pr->right = q;
            while(!st.empty())
            {
                pr = st.top();
                st.pop();
                if(pr->right==q)pr->bf--;
                else pr->bf++;
                if(st.empty()==false)
                {
                    ppr = st.top();
                    st.pop();
                    dd = (ppr->left==pr)?-1:1;
                }
                else dd=0;
                if(pr->bf==1 || pr->bf==-1)break;
                if(pr->bf!=0)
                {
                    if(pr->bf<0){d=-1;q=pr->left;}
                    else{d=1;q=pr->right;}
                    if(q->bf==0)
                        {
                            if(d==-1)
                            {
                            RotateR(pr);pr->bf=1;pr->right->bf=-1;
                            }
                        else
                            {
                            RotateL(pr);pr->bf=-1;pr->left->bf=1;
                            } 
                    break;
                        }
                        if(q->bf==d)
                        {
                            if(d==-1)RotateR(pr);
                            else RotateL(pr);
                        }
                        else
                        {
                            if(d==-1)RotateLR(pr);
                            else RotateRL(pr);
                        }
                        if(dd==-1)ppr->left=pr;
                        else if(dd==-1)ppr->right=pr;
                }
            q=pr;
            }
            if(st.empty()==true)ptr=pr;
        }
        delete p;return true;
    }
    public:
    void show()
    {
        show(root);
    }
    void show(VALNode<Type> *t)
    {
        if(t==NULL)return ;
        else
        {
            show(t->left);
            cout<<t->data<< "  ";
            show(t->right);  
        }
    }
private:
    VALNode<Type> *root;
};
int main()
{   
    int a[]={4,7,5};
    VALTree<int> val;
    val.Insert(a,3);
    val.show();
    val.Remove(4);
    cout<<endl;
    val.show();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值