Balanced tree --Treap, Splay

Binary search tree (BST) two properties:

 

    1. The key of the node key is not less than its left subtree of any node

 

    2. The key is not greater than the node key of its right subtree of any node

 

Obviously, the binary tree traversal order is monotonously ascending key sequence.

 

To avoid cross-border, is inserted in the key BST for positive and negative infinity junction initial situation.

 

 

Basic operation:

 

1. Retrieve

 

   Recursion:

   (1) Find the node, the return value

   (2) and the node is not found nowhere (child node is empty), returns

   (3) junction is too large, the left recursively

   (4) small nodes, right recursively

   ps: write cycle can also be used, but I used it to search deep

 

2. Insert

   

   If the key value is found in the node does not exist, the new node.

 

3. Ranking (Kth)

 

   I.e., the size of the left subtree +1 balance of properties by rating tree, a node.

 

4. predecessor / successor

   First, find the node tree according to the equilibrium properties:

    If you are looking for its predecessor, the first step to go to the left (looking than the left sub-tree node dot in), with

    After constantly go to the right until a leaf node is the number of nodes smaller than the point of one of the largest.

    After both empathy.

    

5. Delete

    

   First, the retrieved node.

      If the number of child nodes is less than 2 p, p deleted directly, so that the direct child node instead of its position connected to the parent node p.

      P If there are both left subtree right subtree, find the successor node p's next. If there is no next left subtree delete next, and so next right subtree instead of the position of the next. Finally, let the next node instead of p nodes, you can delete p.

 

 

Treap (single rotation)

 

The following is the general balance treap write code tree (BZOJ3224), the code is almost Li Yudong of "algorithm contest Step-up Guide" above looks (a favorite book).

 

  1 #include<iostream>
  2 #include<cstdlib>
  3 using namespace std;
  4 const int SIZE = 100005;
  5 struct Treap{
  6     int l, r;
  7     int val, dat;
  8     int size, cnt;
  9 }a[SIZE];
 10 int tot, n, root, INF = 0x7fffffff;
 11 int New(int val){
 12     a[++tot].val = val;
 13     a[tot].size = a[tot].cnt = 1;
 14     a[tot].dat = rand();
 15     return tot;
 16 }
 17 void Update(int p){
 18     a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
 19 }
 20 
 21 void Build(){
 22     New(-INF), New(INF);
 23     root = 1, a[1].r = 2;
 24     Update(root);
 25 }
 26 
 27 void zig(int &p){
 28     int q = a[p].l;
 29     a[p].l = a[q].r, a[q].r = p, p = q;
 30     Update(a[p].r), Update(p);
 31 }
 32 void zag(int &p){
 33     int q = a[p].r;
 34     a[p].r = a[q].l, a[q].l = p, p = q;
 35     Update(a[p].l), Update(p);
 36 }
 37 void Insert(int &p, int val){
 38     if(p == 0) {
 39         p = New(val);
 40         return ;
 41     }
 42     if(val == a[p].val){
 43         a[p].cnt++, Update(p);
 44         return ;
 45     }
 46     if(val < a[p].val){
 47         Insert(a[p].l, val);
 48         if(a[p].dat < a[a[p].l].dat) zig(p);
 49     }
 50     else{
 51         Insert(a[p].r, val);
 52         if(a[p].dat < a[a[p].r].dat) zag(p); 
 53     }
 54     Update(p);
 55 }
 56 void Remove(int &p, int val){
 57     if(p == 0) return;
 58     if(val == a[p].val){
 59         if(a[p].cnt > 1){
 60             a[p].cnt--, Update(p);
 61             return;
 62         }
 63         if(a[p].l || a[p].r){
 64             if(a[p].r == 0 || a[a[p].l].dat > a[a[p].r].dat) 
 65                 zig(p), Remove(a[p].l, val);
 66             else 
 67                 zag(p), Remove(a[p].r, val);
 68             Update(p);
 69         }else p = 0;
 70     }
 71     val < a[p].val ? Remove(a[p].l, val) : Remove(a[p].r, val);
 72     Update(p); 
 73 }
 74 int GetRankByVal(int p, int val){
 75     if(p == 0) return 0;
 76     if(a[p].val == val) return a[a[p].l].size;
 77     if(val < a[p].val) return GetRankByVal(a[p].l, val);
 78     return GetRankByVal(a[p].r, val) + a[a[p].l].size + a[p].cnt;
 79 } 
 80 int GetValByRank(int p, int rank){
 81     if(p == 0) return INF;
 82     if(a[a[p].l].size >= rank) return GetValByRank(a[p].l, rank);
 83     if(a[a[p].l].size + a[p].cnt >= rank) return a[p].val;
 84     return GetValByRank(a[p].r, rank - a[a[p].l].size - a[p].cnt);
 85 }
 86 
 87 int GetPrev(int val){
 88     int ans = 1;
 89     int p = root;
 90     while(p){
 91         if(val == a[p].val){
 92             if(a[p].l > 0){
 93                 p = a[p].l;
 94                 while(a[p].r) p = a[p].r;
 95                 ans = p;
 96             }
 97             break;
 98         }
 99         if(a[p].val < val && a[p].val > a[ans].val) ans = p;
100         p = val < a[p].val ? a[p].l : a[p].r; 
101     }
102     return a[ans].val;
103 }
104 int GetNext(int val){
105     int ans = 2;
106     int p = root;
107     while(p){
108         if(val == a[p].val){
109             if(a[p].r > 0){
110                 p = a[p].r;
111                 while(a[p].l) p = a[p].l;
112                 ans = p;
113             }
114             break;
115         }
116         if(a[p].val > val && a[p].val < a[ans].val) ans = p;
117         p = val < a[p].val ? a[p].l : a[p].r;
118     }
119     return a[ans].val;
120 }
121 
122 int main(){
123     Build();
124     int n;
125     cin >> n;
126     while(n--){
127         int f, x;
128         cin >> f >> x;
129         switch(f){
130             case 1:
131                 Insert(root, x);
132                 break;
133             case 2:
134                 Remove(root, x);
135                 break;
136             case 3:
137                 cout << GetRankByVal(root, x) <<"\n";
138                 break;
139             case 4:
140                 cout << GetValByRank(root, x+1) <<"\n";
141                 break;
142             case 5:
143                 cout << GetPrev(x) <<"\n";
144                 break;
145             case 6:
146                 cout << GetNext(x) <<"\n";
147                 break;
148         }
149     }
150     return 0;
151 }

splay(伸展树)

 

   伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。

   概括的说其操作——把一个结点旋转到根。

   概括的说其转法——如果结点是父结点的左子节点,则进行右旋;如果结点是父节点的右子节点,则进行左旋。

   

   逐渐可以理解转的原理的。

   

  1 #include<bits/stdc++.h>
  2    using namespace std;
  3    
  4    const int _=1e5+20;
  5    
  6    int n,opt,x;
  7    
  8    struct Splay
  9    {
 10        int root,cnt,val[_],ch[_][2],siz[_],sz[_],par[_];
 11    
 12        bool chk(int x)
 13        {
 14            return ch[par[x]][1]==x;
 15        }
 16    
 17        void pushup(int x)
 18        {
 19            if (!x) return;
 20            siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+sz[x];
 21            //cout<<x<<' '<<siz[x]<<"       ";
 22        }
 23    
 24        int newnode(int x)
 25        {
 26            ++cnt;
 27            val[cnt]=x,sz[cnt]=siz[cnt]=1;
 28            ch[cnt][0]=ch[cnt][1]=0;
 29            return cnt;
 30        }
 31    
 32        void rotate(int x)
 33        {
 34            int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
 35            ch[y][k]=w,par[w]=y;
 36            ch[z][chk(y)]=x,par[x]=z;
 37            ch[x][k^1]=y,par[y]=x;
 38            pushup(y),pushup(x);
 39        }
 40    
 41        void splay(int x,int goal=0)
 42        {
 43            while (par[x]!=goal)
 44            {
 45                int y=par[x],z=par[y];
 46                if (z!=goal)
 47                {
 48                    if (chk(x)==chk(y)) rotate(y);
 49                    else rotate(x);    
 50                }
 51                rotate(x);
 52            }
 53            if (!goal) root=x;
 54        }
 55    
 56        void insert(int x)
 57        {
 58            int cur=root,p=0;
 59            while (cur && x!=val[cur]) p=cur,cur=ch[cur][x>val[cur]];
 60            if (cur) ++sz[cur],splay(cur);
 61            else cur=ch[p][x>val[p]]=newnode(x),par[cur]=p,splay(cur);
 62        }
 63    
 64        void find(int x)
 65        {
 66            if (!root) return;
 67            int cur=root;
 68            while (ch[cur][x>val[cur]] && x!=val[cur]) cur=ch[cur][x>val[cur]];
 69            splay(cur);
 70        }
 71    
 72        int rank(int x)
 73        {
 74            find(x);
 75            return siz[ch[root][0]]+1;
 76        }
 77    
 78        int kth(int k)
 79        {
 80            int cur=root;
 81            while (true)
 82            {
 83                if (ch[cur][0] && k<=siz[ch[cur][0]]) cur=ch[cur][0];
 84                else if (k>siz[ch[cur][0]]+sz[cur]) k-=siz[ch[cur][0]]+sz[cur],cur=ch[cur][1];
 85                else return cur;
 86            }
 87        }
 88    
 89        int pre(int x)
 90        {
 91            find(x);
 92            if (val[root]<x) return root;
 93            int cur=ch[root][0];
 94            while (ch[cur][1]) cur=ch[cur][1];
 95            return cur;
 96        }
 97    
 98        int suc(int x)
 99        {
100            find(x);
101            if (val[root]>x) return root;
102            int cur=ch[root][1];
103            while (ch[cur][0]) cur=ch[cur][0];
104            return cur;
105        }
106    
107        void remove(int x)
108        {
109            int u=pre(x),v=suc(x);
110            //cout<<u<<' '<<v<<endl;
111            splay(u),splay(v,u);
112            int w=ch[v][0];
113            if (sz[w]>1) --sz[w],splay(w);
114            else siz[0]=sz[0]=ch[v][0]=0;
115            //pushup(v),pushup(u);
116        }
117    
118        void maintain(int x)
119        {
120            if (!ch[x][0] && !ch[x][1]) siz[x]=sz[x];
121            if (ch[x][0]) maintain(ch[x][0]);
122            if (ch[x][1]) maintain(ch[x][1]);
123            pushup(x);
124        }
125    
126        void print(int x)
127        {
128            cout<<x<<' '<<val[x]<<' '<<sz[x]<<' '<<siz[x]<<' '<<ch[x][0]<<' '<<ch[x][1]<<' '<<endl;
129            if (ch[x][0]) print(ch[x][0]);
130            if (ch[x][1]) print(ch[x][1]);
131        }
132    }T;
133    
134    int main()
135    {
136        T.insert(-0x3f3f3f3f);T.insert(0x3f3f3f3f);
137        cin>>n;
138        for (int i=1; i<=n; i++)
139        {
140            cin>>opt>>x;
141            if (opt==1) T.insert(x);
142            else if (opt==2) T.remove(x);
143            else if (opt==3) cout<<T.rank(x)-1<<'\n';
144            else if (opt==4) cout<<T.val[T.kth(x+1)]<<'\n';
145            else if (opt==5) cout<<T.val[T.pre(x)]<<'\n';
146            else if (opt==6) cout<<T.val[T.suc(x)]<<'\n';
147     }
148        return 0;
149    }

 

Guess you like

Origin www.cnblogs.com/hnoi/p/11355529.html