二叉树系列之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 }

浙公网安备 33010602011771号