SBT 普通平衡树

这是我干过最有勇气的一件事。
为什么我要看这玩意。。好懂难写的玩意

不过也算吧….每天抽空出来,终于把自己的SBT模板打出来了

查询什么的其实挺简单,
主要麻烦在修改和维护上了。

#include
#include
#include
using namespace std;
const int N=100100;int M;
struct ss{
    int key[N],s[N],left[N],right[N];
    int rt,nodecnt;
    void clear(){
        rt=0,nodecnt=0;
        memset(key,0,sizeof(key));
        memset(s,0,sizeof(s));
        memset(left,0,sizeof(left));
        memset(right,0,sizeof(right));
    }; 
    void z_x(int &p){//左旋 
        int k=right[p];
        right[p]=left[k];left[k]=p;
        s[k]=s[p];
        s[p]=s[right[p]]+s[left[p]]+1;
        p=k; 
    }void y_x(int &p){//右旋
        int k=left[p];
        left[p]=right[k];right[k]=p;
        s[k]=s[p];
        s[p]=s[right[p]]+s[left[p]]+1;
        p=k;
    }
    //旋比较简单,不注释了。
    void peace(int &p,bool flag){
        if(!flag){//加到了左子树 
            if(s[left[left[p]]]>s[right[p]]) y_x(p);
            else {//加到了左子树的右子树 
                if(s[right[left[p]]]>s[right[p]]){
                    z_x(left[p]);y_x(p);
                }else return ;
            }
        }else{//反之 
            if(s[right[right[p]]]>s[left[p]])
                z_x(p);
            else{
                if(s[left[right[p]]]>s[left[p]]){
                    y_x(right[p]);z_x(p);
                }else return;
            }
        }
        peace(left[p],false);
        peace(right[p],true);
        peace(p,true);
        peace(p,false);
    }//平衡...也比较简单,不说了。
    void insert(int &p,int x){//加入一个值为x的数 
        if(!p){
            p=++nodecnt;key[p]=x;s[p]=1;
            return;
        }s[p]++;
        if(xelse insert(right[p],x);
        peace(p,x>=key[p]);
    }//插入一个数....也比找到合适的位置就好。

    int del(int &p,int x){//删除一个值为x的数 
        s[p]--;int tmp;
        if(x==key[p]||(xkey[p]&&!right[p])){
            tmp=key[p];
            if(!left[p]||!right[p])
                p=left[p]+right[p];
            else key[p]=del(left[p],key[p]+1);
            return tmp;
        }if(xelse tmp=del(right[p],x);
        return tmp;
    }
    int rank(int &p,int x){//x的排名 
        if(!p) return 1;int tmp=0;
        if(x<=key[p]) tmp=rank(left[p],x);
        else tmp=s[left[p]]+1+rank(right[p],x);
        return tmp;
    }
    int select(int &p,int x){//第x小的数 
        if(x==s[left[p]]+1) return key[p];
        if(x<=s[left[p]]) return select(left[p],x);
        else return select(right[p],x-1-s[left[p]]);
    }
    int pred(int &p,int x){//x的前驱
        if(!p) return x;int tmp;
        if(x<=key[p]) tmp=pred(left[p],x);
        else{tmp=pred(right[p],x);if(tmp==x)tmp=key[p];}
        return tmp;
    }int succ(int &p,int x){//x的后驱
        if(!p)return x;int tmp;
        if(x>=key[p]) tmp=succ(right[p],x);
        else{tmp=succ(left[p],x);if(tmp==x)tmp=key[p];}
        return tmp;
    }   
}T;
int main(){
    T.clear();scanf("%d",&M);
    int &rt=T.rt=0;
    while(M--){
        int opt,x;scanf("%d%d",&opt,&x);
        if(opt==1) T.insert(rt,x);
        else if(opt==2) T.del(rt,x);
        else if(opt==3) printf("%d\n",T.rank(rt,x));
        else if(opt==4) printf("%d\n",T.select(rt,x));
        else if(opt==5) printf("%d\n",T.pred(rt,x));
        else if(opt==6) printf("%d\n",T.succ(rt,x)); 
    }return 0;
}

删除操作注:
一直往下找,直到找到这个数,然后把这个数删了,
继续按顺序往下找,直到找到一个可以代替删掉的那个数位置的数,然后返回。

这玩意,,,GG,,我还是学别的内容吧。

你可能感兴趣的:(c++-树)