平衡樹學習筆記

> 平 衡 樹 學 習 筆 記 <


 

目錄

  ) 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更新:

實際操做中,各個變量的值都是不斷更新的,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;}
壓行平衡樹
相關文章
相關標籤/搜索