首页 > 代码库 > 几种平衡树

几种平衡树

 

 

技术分享
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #define ls(x) (x->ch[0])
  5 #define rs(x) (x->ch[1])
  6 #define sz(x) (x->size)
  7 #define p(x) (x->p)
  8 using namespace std;
  9 const int INF=0x7fffffff;
 10 struct son
 11 {
 12     int v,size;
 13     son *ch[2],*p;
 14     son(int x)
 15     {
 16         v=x;size=1;
 17     }
 18 };
 19 son *root,*null;
 20 son* newson(int val)
 21 {
 22     son *x=new son(val);
 23     ls(x)=rs(x)=p(x)=null;
 24     return x;
 25 }
 26 void pushup(son *x){sz(x)=sz(ls(x))+sz(rs(x))+1;}
 27 int rank(int val)
 28 {
 29     son *x=root;
 30     int ans=0;
 31     while(x!=null)
 32     {
 33         if(val>x->v){ans+=(sz(ls(x))+1);x=rs(x);}
 34         else x=ls(x);
 35     }
 36     return ans;
 37 }
 38 son* kth(int k)
 39 {
 40     //printf("sha bi qin shi yu\n");
 41     son *x=root;
 42     while(x!=null)
 43     {
 44         if(sz(ls(x))+1==k)return x;
 45         if(sz(ls(x))+1>k)x=ls(x);
 46         else {k-=(sz(ls(x))+1);x=rs(x);}
 47     }
 48     return null;
 49 }
 50 int islc(son *x){return ls(p(x))==x;}
 51 // is left child ???
 52 //x在右,就左旋  在左,就右旋 
 53 void rot(son *x,int d)
 54 {
 55     son *y=x->ch[d^1];
 56     if(p(x)!=null)p(x)->ch[islc(x)^1]=y;//祖父儿子=y
 57     else root=y;
 58     p(y)=p(x);//把祖父儿子设成y 
 59     x->ch[d^1]=y->ch[d];//
 60     if(y->ch[d])p(y->ch[d])=x;//把y的d同向儿子改成x的d逆向儿子 
 61     y->ch[d]=x;p(x)=y;//把x的爸爸改成y 
 62     pushup(x);pushup(y); 
 63 }
 64 void splay(son *x,son *t=null)//把x旋到以t为祖父节点 
 65 {
 66     for(son *rt=p(x);rt!=t;rt=p(x))
 67     {
 68         if(p(rt)==t)
 69         {
 70             rot(rt,islc(x));
 71             return ;
 72         }
 73         if(islc(x)==islc(rt))rot(p(rt),islc(rt));//一字型旋转 第一步 
 74         else rot(rt,islc(x));//之字形旋转 第一步 
 75         rot(p(x),islc(x));//第二步 (此时x已经转上去)
 76     }
 77 }
 78 void add(int val)
 79 {
 80     int pos=rank(val);//val排名-1 
 81     splay(kth(pos));//把前一个转到root
 82     splay(kth(pos+1),root);//把pos+1的转到root右儿子
 83     //val 卡在pos和pos+1之间 
 84     son *x=newson(val);
 85     root->ch[1]->ch[0]=x;
 86     p(x)=root->ch[1];
 87     pushup(root->ch[1]);pushup(root);
 88 }
 89 void del(int val)
 90 {
 91     int pos=rank(val)+1;
 92     splay(kth(pos-1));splay(kth(pos+1),root);
 93     //把val卡在pos-1和pos+1之间
 94     root->ch[1]->ch[0]=null;
 95     pushup(root->ch[1]);pushup(root);
 96 }
 97 int n;
 98 
 99 int main(){
100     //freopen("phs.in","r",stdin);
101     //freopen("phs.out","w",stdout);
102     null=new son(0);sz(null)=0;
103     root=newson(-INF);
104     root->ch[1]=newson(INF);//即把一开始的区间调成-INF到INF
105     p(root->ch[1])=root; 
106     scanf("%d",&n);
107     for(int i=1;i<=n;++i)
108     {
109         int opt,x;scanf("%d%d",&opt,&x);
110         switch(opt)
111         {
112             case 1:add(x);break;
113             case 2:del(x);break;
114             case 3:printf("%d\n",rank(x));break;
115             //返回值就是rank的原因:********
116             //一开始root的值=-INF root右儿子=INF *******
117             //每次查找一定会到这两个节点,而他们size=1 
118             case 4:printf("%d\n",kth(x+1)->v);break;
119             //不能轻易在rank上+1,必须在x上+1 
120             case 5:printf("%d\n",kth(rank(x))->v);break;
121             case 6:printf("%d\n",kth(rank(x+1)+1)->v);break;
122         }
123     }
124     while(1);
125     return 0;
126 }
Splay详细注释

 

 

 

技术分享
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define ls(x) (x->l)
  6 #define rs(x) (x->r)
  7 #define sz(x) ((x)?(x->size):(0))
  8 using namespace std;
  9 struct Treap
 10 {
 11     struct treap
 12     {
 13         int size,fix,val;
 14         treap *l,*r;
 15         treap(int x)
 16         {
 17             val=x;fix=rand();size=1;
 18             l=r=NULL;
 19         }
 20     }*root;
 21     void pushup(treap *x){x->size=sz(ls(x))+sz(rs(x))+1;}
 22     void lturn(treap *&x)
 23     {
 24         treap *y=rs(x);
 25         rs(x)=ls(y);pushup(x);
 26         ls(y)=x;pushup(y);
 27         x=y;
 28     }
 29     void rturn(treap *&x)
 30     {
 31         treap *y=ls(x);
 32         ls(x)=rs(y);pushup(x);
 33         rs(y)=x;pushup(y);
 34         x=y;
 35     }
 36     void add(treap *&x,int val)
 37     {
 38         if(x==NULL)
 39         {
 40             x=new treap(val);
 41             return ;
 42         }
 43         if(val<x->val)
 44         {
 45             add(ls(x),val);
 46             pushup(x);
 47             if(ls(x)->fix>x->fix)rturn(x);
 48         }
 49         else
 50         {
 51             add(rs(x),val);
 52             pushup(x);
 53             if(rs(x)->fix>x->fix)lturn(x);
 54         }
 55     }
 56     void del(treap *&x,int val)
 57     {
 58         if(val==x->val)
 59         {
 60             if(ls(x)&&rs(x))
 61             {
 62                 if(ls(x)->fix>rs(x)->fix){rturn(x);del(rs(x),val);}
 63                 else {lturn(x);del(ls(x),val);}
 64             }
 65             else
 66             {
 67                 treap *y=NULL;
 68                 if(ls(x))y=ls(x);
 69                 else y=rs(x);
 70                 delete x;x=y;
 71             }
 72         }
 73         else
 74         {
 75             if(val<x->val)del(ls(x),val);
 76             else del(rs(x),val);
 77         }
 78         if(x)pushup(x);
 79     }
 80     int rank(int val)
 81     {
 82         treap *x=root;
 83         int ans=0;
 84         while(x)
 85         {
 86             if(val>x->val){ans+=(sz(ls(x))+1);x=rs(x);}
 87             else x=ls(x);
 88         }
 89         return ans;
 90     }
 91     treap* kth(int k)
 92     {
 93         treap *x=root;
 94         while(x)
 95         {
 96             int size=sz(ls(x))+1;
 97             if(size==k)return x;
 98             if(size>=k)x=ls(x);
 99             // = 向右走,因为add的时候就是向右 
100             else {k-=size;x=rs(x);}
101         }
102     }
103 }T;
104 
105 int m,u,o;
106 
107 int main(){
108     //freopen("phs.in","r",stdin);
109     //freopen("phs.out","w",stdout);
110     scanf("%d",&m);
111     while(m--)
112     {
113         scanf("%d%d",&u,&o);
114         if(u==1)T.add(T.root,o);
115         else if(u==2)T.del(T.root,o);
116         else if(u==3)printf("%d\n",T.rank(o)+1);
117         else if(u==4)printf("%d\n",T.kth(o)->val);
118         else if(u==5)printf("%d\n",T.kth(T.rank(o))->val);
119         else printf("%d\n",T.kth(T.rank(o+1)+1)->val);
120         //加2有可能返回一个空指针,炸掉你 
121     }
122     while(1);
123     return 0;
124 }
旋转Treap

 

几种平衡树