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 }