模板——Treap实现名次树

 

Treap 是一种通过赋予结点随机权值的一种满足堆性质二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性。

 

名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点树

名次树支持两个操作:
Kth(x): 找出第k小(第k大)的元素。

Rank(x): 值x的名次,即比x小(大)的结点个数加 1 。

以第k大为例,代码如下:

 1 struct Node {
 2     Node *ch[2];
 3     int r; //随机权值
 4     int v; //值
 5     int s; //附加域size
 6     Node(int vv): v(vv) {
 7         s = 1;
 8         ch[0] = ch[1] = NULL;
 9         r = rand();
10     }
11     int cmp(int x) const {
12         if(x == v) return -1;
13         return x < v ? 0 : 1;
14     }
15     void maintain() {
16         s = 1;
17         if(ch[0] != NULL) s += ch[0]->s;
18         if(ch[1] != NULL) s += ch[1]->s;
19     }
20 };
21 
22 void rotate(Node* &o, int d) { //旋转操作
23     Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
24     o->maintain(); k->maintain(); o = k;
25 }
26 
27 void insert(Node* &o, int x) { //插入操作
28     if(o == NULL) o = new Node(x);
29     else {
30         int d = x < o->v ? 0 : 1;  //注意相等时处理方式可以改变  
31         insert(o->ch[d], x);
32         if(o->ch[d]->r > o->r) rotate(o, d^1);
33     }
34     o->maintain();
35 }
36 void remove(Node* &o, int x) { //删除操作
37     int d = o->cmp(x);
38     Node* u = o;
39     if(d == -1) {
40         if(o->ch[0] != NULL && o->ch[1] != NULL){
41             int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0;
42             rotate(o, d2);
43             remove(o->ch[d2], x);
44         }
45         else {
46             if(o->ch[0] == NULL) o = o->ch[1]; else o = o->ch[0];
47             delete u;
48         }
49     }
50     else remove(o->ch[d], x);
51     if(o != NULL) o->maintain();
52 }
53 
54 int kth(Node* o, int k) {  //找第k大
55     if(o == NULL || k > o->s || k <= 0) return 0;
56     int s = o->ch[1] == NULL ? 0 : o->ch[1]->s;
57     if(k == s+1) return o->v;
58     else if(k <= s) return kth(o->ch[1], k);
59     else return kth(o->ch[0], k-s-1);
60 }

 

posted @ 2016-12-15 19:33  kiraa  阅读(824)  评论(0编辑  收藏  举报