首页 > 代码库 > 平衡二叉树 treap 初见
平衡二叉树 treap 初见
treap通过左右旋维护了一个二叉查找树,根据随机的优先级建立满足优先级大根堆的二叉查找树,在实践中有不错的食府,code也简单。
cogs1829 普通平衡树
题目大意:进行插入、删除、名次、前驱后继。
思路:前面的三种操作都很普通,前驱后继有两种做法(非常不正统吧。。。):1)找到这个数的名次,然后+-1,(如果是后继,并且和原数相同就名次+1,直到不同);2)进行递归查找,以前驱为例:如果这个点的值比x小,就更新一下前驱,找他的右子树,如果>=x,就找他的左子树。这里有可能出现插入多个重复的数,我们可以再开一个域num,记录这种数的个数,然后在操作中相应的进行更改。
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;struct Node{ Node *ch[2]; int r,v,s,num; Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;} int cmp(int x) const{ if (x==v) return -1; else return x<v?0:1; } void Maintain(){ s=num; if (ch[0]!=NULL) s+=ch[0]->s; if (ch[1]!=NULL) s+=ch[1]->s; }};Node* root;void rotate(Node* &o,int d){ Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o; o->Maintain();k->Maintain();o=k;}void insert(Node* &o,int x){ if (o==NULL) o=new Node(x); else { int d=o->cmp(x); if (d==-1) ++o->num; else { insert(o->ch[d],x); if (o->ch[d] ->r > o->r) rotate(o,d^1); } } o->Maintain();}void del(Node* &o,int x){ int d=o->cmp(x); if (d==-1) { if (o->num==1) { if (o->ch[0]==NULL) o=o->ch[1]; else { if (o->ch[1]==NULL) o=o->ch[0]; else { int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0); rotate(o,d2);del(o->ch[d2],x); } } } else --o->num; } else del(o->ch[d],x); if (o!=NULL) o->Maintain();}int rank(Node* &o,int x){ int d=o->cmp(x); if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1); else { if (d==0) return rank(o->ch[d],x); else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num); }}int kth(Node* &o,int x){ if (o==NULL||x<=0||x > o->s) return 0; int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s); if (x>=s+1&&x<=s+ o->num) return o->v; if (x<=s) return kth(o->ch[0],x); else return kth(o->ch[1],x-s- o->num);}int main(){ freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); int n,i,j,x,t,k; scanf("%d",&n); for (i=1;i<=n;++i) { scanf("%d%d",&j,&x); if (j==1) insert(root,x); if (j==2) del(root,x); if (j==3) { t=rank(root,x); printf("%d\n",t); } if (j==4) { t=kth(root,x); printf("%d\n",t); } if (j==5) { insert(root,x); k=rank(root,x); t=kth(root,k-1); del(root,x); printf("%d\n",t); } if (j==6) { insert(root,x); k=rank(root,x); t=kth(root,k+1); while(t==x) { ++k;t=kth(root,k+1); } del(root,x); printf("%d\n",t); } } fclose(stdin); fclose(stdout);}
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;struct Node{ Node *ch[2]; int r,v,s,num; Node(int v):v(v) {ch[0]=ch[1]=NULL;r=rand();s=1;num=1;} int cmp(int x) const{ if (x==v) return -1; else return x<v?0:1; } void Maintain(){ s=num; if (ch[0]!=NULL) s+=ch[0]->s; if (ch[1]!=NULL) s+=ch[1]->s; }};Node* root;int t;void rotate(Node* &o,int d){ Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o; o->Maintain();k->Maintain();o=k;}void insert(Node* &o,int x){ if (o==NULL) o=new Node(x); else { int d=o->cmp(x); if (d==-1) ++o->num; else { insert(o->ch[d],x); if (o->ch[d] ->r > o->r) rotate(o,d^1); } } o->Maintain();}void del(Node* &o,int x){ int d=o->cmp(x); if (d==-1) { if (o->num==1) { if (o->ch[0]==NULL) o=o->ch[1]; else { if (o->ch[1]==NULL) o=o->ch[0]; else { int d2=(o->ch[0] ->r > o->ch[1] ->r ? 1 : 0); rotate(o,d2);del(o->ch[d2],x); } } } else --o->num; } else del(o->ch[d],x); if (o!=NULL) o->Maintain();}int rank(Node* &o,int x){ int d=o->cmp(x); if (d==-1) return (o->ch[0]==NULL ? 1 : o->ch[0] ->s +1); else { if (d==0) return rank(o->ch[d],x); else return rank(o->ch[d],x) + (o->ch[0]==NULL ? o->num : o->ch[0] ->s +o->num); }}int kth(Node* &o,int x){ if (o==NULL||x<=0||x > o->s) return 0; int s=(o->ch[0]==NULL ? 0 : o->ch[0] ->s); if (x>=s+1&&x<=s+ o->num) return o->v; if (x<=s) return kth(o->ch[0],x); else return kth(o->ch[1],x-s- o->num);}void pre(Node* &o,int x){ if (o->v >=x) { if (o->ch[0]!=NULL) pre(o->ch[0],x); } else { t=max(t,o->v); if (o->ch[1]!=NULL) pre(o->ch[1],x); }}void succ(Node* &o,int x){ if (o->v <=x) { if (o->ch[1]!=NULL) succ(o->ch[1],x); } else { t=min(t,o->v); if (o->ch[0]!=NULL) succ(o->ch[0],x); }}int main(){ freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); int n,i,j,x; scanf("%d",&n); for (i=1;i<=n;++i) { scanf("%d%d",&j,&x); if (j==1) insert(root,x); if (j==2) del(root,x); if (j==3) { t=rank(root,x); printf("%d\n",t); } if (j==4) { t=kth(root,x); printf("%d\n",t); } if (j==5) { t=-2100000000; pre(root,x); printf("%d\n",t); } if (j==6) { t=2100000000; succ(root,x); printf("%d\n",t); } } fclose(stdin); fclose(stdout);}
平衡二叉树 treap 初见
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。