) 1 -- > 平衡樹簡介node
) 2 -- > 平衡樹實現ios
| 1 = = > > 平衡樹存儲c++
1 struct node{ 2 int size,value,num,rand; 3 int son[2]; 4 }n[1000001];
size就是節點的個數。ide
value是節點表明的權值。函數
權值相同的兩個節點被視爲一個,num記錄摺疊數量。學習
rand是隨機數,用來維護平衡樹。spa
son就是兩個兒子。3d
實際操做中,各個變量的值都是不斷更新的,size也不例外。code
函數體:blog
1 inline void pushup(int root){}
一個節點包括的節點個數用腳也能想到:左兒子size與右兒子size的和,加上這個節點摺疊數量。
1 n[root].size = n[n[root].son[0]].size + n[n[root].son[1]].size + n[root].num;
完整的平衡樹size更新代碼:
1 inline void pushup(int root) 2 { 3 n[root].size = n[n[root].son[0]].size + n[n[root].son[1]].size + n[root].num; 4 }
學習完上面的內容,接下來的基本逼死人的操做插入與刪除就很簡單了:
因爲Treap = Tree + Heap
因此平衡樹插入與二叉排序樹插入差很少
函數體:
1 inline void add(int &root,int data){}
插入節點總會遇到各類增長碼量的狀況,須要咱們一一判斷:
[ 1 ]節點不存在
什麼??節點不存在??殺了出題人!
當插入函數用在建樹中,這種狀況很常見。
沒有節點,那咱們就開墾一個節點。(水土流失,土地荒漠化請走開)
├ 節點總數加1
├ 新節點size爲1
├ 新節點num爲1
├ 權值爲data
└ 生成rand
→→→嶄新的節點!!(不要998,不要98,只要9.8!)
代碼實現就是一個簡單的模擬:
奇怪的行號 if(!root) 9 { 8 sum+=1; 7 root=sum; 6 n[root].size=1; 5 n[root].num=1; 4 n[root].value=data; 3 n[root].rand=rand(); 2 return; 1 }
0 點火,起飛!!
[ 2 ]有一個權值爲data的節點
那更簡單了!!
1 if (n[root].value==data) 2 { 3 n[root].num+=1; 4 n[root].size+=1; 5 return; 6 }
[ 3 ]尋找子樹知足狀況一或狀況二
去哪棵子樹呢??定義一個變量。
1 int d(data>n[root].value);
有了明確的方向,就應該堅持走下去:
1 add(n[root].son[d],data);
隨機數判斷,隨機旋轉:
1 if(n[root].rand<n[n[root].son[d]].rand) 2 rotate(root,d^1);
更新size:
1 pushup(root);
至此,插入操做基本完成。
完整平衡樹插入代碼:
1 inline void add(int &root,int data) 2 { 3 if (!root) 4 { 5 sum+=1; 6 root=sum; 7 n[root].size=1; 8 n[root].num=1; 9 n[root].value=data; 10 n[root].rand=rand(); 11 return; 12 } 13 if (n[root].value==data) 14 { 15 n[root].num+=1; 16 n[root].size+=1; 17 return; 18 } 19 int d(data>n[root].value); 20 add(n[root].son[d],data); 21 if(n[root].rand<n[n[root].son[d]].rand) 22 rotate(root,d^1); 23 pushup(root); 24 }
平衡樹旋轉不破壞平衡樹的性質,也就是說
旋轉前:A<B<C<D<E<F
旋轉後:A<B<C<D<E<F
完整平衡樹旋轉代碼:
1 inline void rotate(int &root,int way) 2 { 3 int copy=n[root].son[way^1]; 4 n[root].son[way^1]=n[copy].son[way]; 5 n[copy].son[way]=root; 6 pushup(root);pushup(copy); 7 root=copy; 8 }
1 inline void remove(int &root,int data) 2 { 3 if(!root) return; 4 if(data<n[root].value) remove(n[root].son[0],data); 5 else if(data>n[root].value) remove(n[root].son[1],data); 6 else 7 { 8 if((!n[root].son[0])&&(!n[root].son[1])) 9 { 10 n[root].num-=1,n[root].size-=1; 11 if(n[root].num==0) root=0; 12 } 13 else if(n[root].son[0]&&!n[root].son[1]) 14 { 15 rotate(root,1);remove(n[root].son[1],data); 16 } 17 else if(!n[root].son[0]&&n[root].son[1]) 18 { 19 rotate(root,0);remove(n[root].son[0],data); 20 } 21 else if(n[root].son[0]&&n[root].son[1]) 22 { 23 int d=(n[n[root].son[0]].rand>n[n[root].son[1]].rand); 24 rotate(root,d);remove(n[root].son[d],data); 25 } 26 } 27 pushup(root); 28 }
1 inline int rank(int root,int data) 2 { 3 if(!root) 4 return 0; 5 if(n[root].value==data) 6 return n[n[root].son[0]].size+1; 7 if(n[root].value<data) 8 return n[n[root].son[0]].size+n[root].num+rank(n[root].son[1],data); 9 if(n[root].value>data) 10 return rank(n[root].son[0],data); 11 }
1 inline int find(int root,int data) 2 { 3 if(!root) 4 return 0; 5 if(n[n[root].son[0]].size>=data) 6 return find(n[root].son[0],data); 7 else if(n[n[root].son[0]].size+n[root].num<data) 8 return find(n[root].son[1],data-n[root].num-n[n[root].son[0]].size); 9 else 10 return n[root].value; 11 }
inline int maxmin(int __a,int __b,int __bool) { if(__bool) return max(__a,__b); else return min(__a,__b); } inline int pan(int __a,int __b,int __bool) { if(__bool) return (__a>=__b?1:0); else return (__a<=__b?1:0); } inline int findin(int root,int data,int way) { if(!root) return inf+way; if(pan(n[root].value,data,way)) return findin(n[root].son[way^1],data,way); else return maxmin(n[root].value,findin(n[root].son[way],data,way),way); }
看道板子題:P3369
完整代碼:
1 #include<bits/stdc++.h> 2 #define inf 2147483647 3 using namespace std; 4 int sum=0,tree_root=0; 5 struct node{ 6 int size,value,num,rand; 7 int son[2]; 8 }n[1000001]; 9 inline int maxmin(int __a,int __b,int __bool) 10 { 11 if(__bool) return max(__a,__b); 12 else return min(__a,__b); 13 } 14 inline void pushup(int root){n[root].size=n[n[root].son[0]].size+n[n[root].son[1]].size+n[root].num;} 15 inline void rotate(int &root,int way) 16 { 17 int copy=n[root].son[way^1]; 18 n[root].son[way^1]=n[copy].son[way]; 19 n[copy].son[way]=root; 20 pushup(root);pushup(copy); 21 root=copy; 22 } 23 inline void add(int &root,int data) 24 { 25 if (!root) 26 { 27 sum+=1; 28 root=sum; 29 n[root].size=1; 30 n[root].num=1; 31 n[root].value=data; 32 n[root].rand=rand(); 33 return; 34 } 35 if (n[root].value==data) 36 { 37 n[root].num+=1; 38 n[root].size+=1; 39 return; 40 } 41 int d(data>n[root].value); 42 add(n[root].son[d],data); 43 if(n[root].rand<n[n[root].son[d]].rand) 44 rotate(root,d^1); 45 pushup(root); 46 } 47 inline void remove(int &root,int data) 48 { 49 if(!root) return; 50 if(data<n[root].value) remove(n[root].son[0],data); 51 else if(data>n[root].value) remove(n[root].son[1],data); 52 else 53 { 54 if((!n[root].son[0])&&(!n[root].son[1])) 55 { 56 n[root].num-=1,n[root].size-=1; 57 if(n[root].num==0) root=0; 58 } 59 else if(n[root].son[0]&&!n[root].son[1]) 60 { 61 rotate(root,1);remove(n[root].son[1],data); 62 } 63 else if(!n[root].son[0]&&n[root].son[1]) 64 { 65 rotate(root,0);remove(n[root].son[0],data); 66 } 67 else if(n[root].son[0]&&n[root].son[1]) 68 { 69 int d=(n[n[root].son[0]].rand>n[n[root].son[1]].rand); 70 rotate(root,d);remove(n[root].son[d],data); 71 } 72 } 73 pushup(root); 74 } 75 inline int rank(int root,int data) 76 { 77 if(!root) 78 return 0; 79 if(n[root].value==data) 80 return n[n[root].son[0]].size+1; 81 if(n[root].value<data) 82 return n[n[root].son[0]].size+n[root].num+rank(n[root].son[1],data); 83 if(n[root].value>data) 84 return rank(n[root].son[0],data); 85 } 86 inline int find(int root,int data) 87 { 88 if(!root) 89 return 0; 90 if(n[n[root].son[0]].size>=data) 91 return find(n[root].son[0],data); 92 else if(n[n[root].son[0]].size+n[root].num<data) 93 return find(n[root].son[1],data-n[root].num-n[n[root].son[0]].size); 94 else 95 return n[root].value; 96 } 97 inline int pan(int __a,int __b,int __bool) 98 { 99 if(__bool) return (__a>=__b?1:0); 100 else return (__a<=__b?1:0); 101 } 102 inline int findin(int root,int data,int way) 103 { 104 if(!root) return inf+way; 105 if(pan(n[root].value,data,way)) return findin(n[root].son[way^1],data,way); 106 else return maxmin(n[root].value,findin(n[root].son[way],data,way),way); 107 } 108 int main() 109 { 110 int n,opt,x; 111 scanf("%d",&n); 112 for(register int i=0;i<n;++i) 113 { 114 scanf("%d%d",&opt,&x); 115 if(opt==1) add(tree_root,x); 116 else if(opt==2) remove(tree_root,x); 117 else if(opt==3) printf("%d\n",rank(tree_root,x)); 118 else if(opt==4) printf("%d\n",find(tree_root,x)); 119 else if(opt==5) printf("%d\n",findin(tree_root,x,1)); 120 else if(opt==6) printf("%d\n",findin(tree_root,x,0)); 121 } 122 return 0; 123 }
我的比較喜歡壓行(60行平衡樹見過嗎??)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #define inf 2147483647 5 using namespace std; 6 int sum=0,tree_root=0; 7 struct node{int size,value,num,rand,son[2];}n[500001]; 8 inline int maxmin(int __a,int __b,int __bool){if(__bool) return max(__a,__b);else return min(__a,__b);} 9 inline void pushup(int root){n[root].size=n[n[root].son[0]].size+n[n[root].son[1]].size+n[root].num;} 10 inline void rotate(int &root,int way){ 11 int copy=n[root].son[way^1]; 12 n[root].son[way^1]=n[copy].son[way];n[copy].son[way]=root; 13 pushup(root);pushup(copy);root=copy;} 14 inline void add(int &root,int data){ 15 if (!root){ 16 sum+=1;root=sum; 17 n[root].size=1;n[root].num=1;n[root].value=data;n[root].rand=rand(); 18 return;} 19 if(n[root].value==data){n[root].num+=1,n[root].size+=1;return;} 20 int d(data>n[root].value);add(n[root].son[d],data); 21 if(n[root].rand<n[n[root].son[d]].rand) rotate(root,d^1); 22 pushup(root);} 23 inline void remove(int &root,int data){ 24 if(!root) return; 25 if(data<n[root].value) remove(n[root].son[0],data); 26 else if(data>n[root].value) remove(n[root].son[1],data); 27 else { 28 if((!n[root].son[0])&&(!n[root].son[1])){n[root].num-=1,n[root].size-=1; if(n[root].num==0) root=0;} 29 else if(n[root].son[0]&&!n[root].son[1]){rotate(root,1);remove(n[root].son[1],data);} 30 else if(!n[root].son[0]&&n[root].son[1]){rotate(root,0);remove(n[root].son[0],data);} 31 else if(n[root].son[0]&&n[root].son[1]){ 32 int d=(n[n[root].son[0]].rand>n[n[root].son[1]].rand); 33 rotate(root,d);remove(n[root].son[d],data);}} 34 pushup(root);} 35 inline int rank(int root,int data){ 36 if(!root) return 0; 37 if(n[root].value==data) return n[n[root].son[0]].size+1; 38 if(n[root].value<data) return n[n[root].son[0]].size+n[root].num+rank(n[root].son[1],data); 39 if(n[root].value>data) return rank(n[root].son[0],data);} 40 inline int find(int root,int data){ 41 if(!root) return 0; 42 if(n[n[root].son[0]].size>=data) return find(n[root].son[0],data); 43 else if(n[n[root].son[0]].size+n[root].num<data) return find(n[root].son[1],data-n[root].num-n[n[root].son[0]].size); 44 else return n[root].value;} 45 inline int pan(int __a,int __b,int __bool){if(__bool) return (__a>=__b?1:0);else return (__a<=__b?1:0);} 46 inline int findin(int root,int data,int way){ 47 if(!root) return inf+way; 48 if(pan(n[root].value,data,way)) return findin(n[root].son[way^1],data,way); 49 else return maxmin(n[root].value,findin(n[root].son[way],data,way),way);} 50 int main(){ 51 int n,opt,x; 52 scanf("%d",&n); 53 for(register int i=0;i<n;++i){ 54 scanf("%d%d",&opt,&x); 55 if(opt==1) add(tree_root,x); 56 else if(opt==2) remove(tree_root,x); 57 else if(opt==3) printf("%d\n",rank(tree_root,x)); 58 else if(opt==4) printf("%d\n",find(tree_root,x)); 59 else if(opt==5) printf("%d\n",findin(tree_root,x,1)); 60 else if(opt==6) printf("%d\n",findin(tree_root,x,0));}return 0;}