简述:
Treap=Tree+Heap。Treap树也是一个二叉搜索树,但是他多了一个键值key,这些优先级是是在结点插入时,随机赋予的,Treap根据这些优先级满足堆的性质。要满足堆的性质,treap树则构造了一个旋转函树。
对于treap树,基本的操作有:结点的定义,插入,旋转,找第k大的数,查询某个数
结点的定义:
struct node{
int rank;//优先级
int key;//键值
int size;//这个结点为根结点时的子树的结点总数(用于名次数)
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
int size=1;
if(son[0]!=NULL)size+=son[0]->size;
if(son[1]!=NULL)size+=son[1]->size;
}
};
```cpp
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];
k->son[d]=o;
o->update();
k->update();
o=k;
}
插入:
void insert(node *&o,int x){//插入x
if(o==NULL){
o=new node();
o->son[0]=o->son[1]-NULL;
o->rank=rand();
o->key=x;
o->size=1;
}
else{
int d=o->cmp(x);
insert(o->son[d],x);
o->update();
if(o<o->son[d])
rotate(o,d^1);
}
}
找第k大的数:
int kth (node *o,int k){//返回第k大的数
if(o==NULL||k<=0||k>o->size)
return -1;
int s=o->son[1]==NULL?:o->son[1]->size;
if(k==s+1)return o->key;
else if(k<=s) return kth(o->son[1],k);
else return kth(o->son[0],k-s-1);
}
查询某个数:
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;
}
}
}