二叉树系列之Treap树

          Treap是一棵拥有键值、优先级两种权值的树 

 

struct node{
    int size;//以这个结点为根的子树的结点总数量,用于名次树
    int rank;//优先级
    int key;//键值
    node *son[2];//son[0]是左儿子,son[1]是右儿子
    bool operator<(const node &a)const{return rank<a.rank;}
    int cmp(int x)const{
        if(x==key) return -1;
        return x<key?0:1;
    }
    void update(){//更新size
        size=1;
        if(son[0]!=NULL) size+=son[0]->size;
        if(son[1]!=NULL) size+=son[1]->size;
    }
};

 

 

 

1.唯一性

2.期望的插入、删除、查找的时间复杂度都是O(log2 n)

  查找

int find(node *o,int k){//返回元素k的名次
    if(o==NULL) return -1;
    int d=o->cmp(k);
    if(d==-1) return o->son[1]==NULL?1:o->son[1]->size+1;
    else if(d==1) return find(o->son[d],k);
    else{
        int tmp=find(o->son[d],k);
        if(tmp==-1) return -1;
        else return o->son[1]==NULL?tmp+1:tmp+1+o->son[1]->size;
    }
}

 

3.插入

         

 

 

  

 

                                              (灰色为先前位置)

 

  旋转代码

void rotate(node* &o,int d){      //d=0,左旋;d=1,右旋
    node *k=o->son[d^1];          //d^1与1-d等价,但是更快
    o->son[d^1]=k->son[d];        //图中的x
    k->son[d]=o;    
    o=k;                          //返回新的根
}

 4.删除

  调整至叶子结点后直接删除

void remove(node *&o,int x){
    int d=o->cmp(x);
    if(d==-1){
        if(o->son[0]==NULL) o=o->son[1];
        else if(o->son[1]==NULL) o=o->son[0];
        else{
            int d2=(o->son[0]>o->son[1]?1:0);
            rotate(o,d2);
            remove(o->son[d2],x);
        }
    }
    else remove(o->son[d],x);
}

 

5.分裂与合并问题

6.Treap与名次树问题

  例题:hdu4585 "Shaolin"

  题解地址:https://www.cnblogs.com/ynzhang2020/p/15071130.html

 

百宝箱

 1 struct node{
 2     int size;//以这个结点为根的子树的结点总数量,用于名次树
 3     int rank;//优先级
 4     int key;//键值
 5     node *son[2];//son[0]是左儿子,son[1]是右儿子
 6     bool operator<(const node &a)const{return rank<a.rank;}
 7     int cmp(int x)const{
 8         if(x==key) return -1;
 9         return x<key?0:1;
10     }
11     void update(){//更新size
12         size=1;
13         if(son[0]!=NULL) size+=son[0]->size;
14         if(son[1]!=NULL) size+=son[1]->size;
15     }
16 };
17 void rotate(node *&o,int d){//d=0,左旋;d=1,右旋
18     node *k=o->son[d^1];//d^1与1-d等价,但是更快
19     o->son[d^1]=k->son[d];
20     k->son[d]=o;
21     o->update();
22     k->update();
23     o=k;
24 }
25 void insert(node *&o,int x){//把x插入到树中
26     if(o==NULL){
27         o=new node();
28         o->son[0]=o->son[1]=NULL;
29         o->rank=rand();
30         o->key=x;
31         o->size=1;
32     }
33     else{
34         int d=o->cmp(x);
35         insert(o->son[d],x);
36         o->update();
37         if(o<o->son[d]) rotate(o,d^1);
38     }
39 }
40 int kth(node *o,int k){//返回第k大的数
41     if(o==NULL||k<=0||k>o->size) return -1;
42     int s=o->son[1]==NULL?0:o->son[1]->size;
43     if(k==s+1) return o->key;
44     else if(k<=s) return kth(o->son[1],k);
45     else return kth(o->son[0],k-s-1);
46 }
47 int find(node *o,int k){//返回元素k的名次
48     if(o==NULL) return -1;
49     int d=o->cmp(k);
50     if(d==-1) return o->son[1]==NULL?1:o->son[1]->size+1;
51     else if(d==1) return find(o->son[d],k);
52     else{
53         int tmp=find(o->son[d],k);
54         if(tmp==-1) return -1;
55         else return o->son[1]==NULL?tmp+1:tmp+1+o->son[1]->size;
56     }
57 }
拿来吧你 

 

posted @ 2021-07-29 09:07  努力不秃兔  阅读(123)  评论(0)    收藏  举报