splay 的普通平衡樹功能

來源:互聯網
上載者:User

普通平衡樹的功能主要有   

 插入 刪除 一個數

 找 前驅  後繼  第k大 小

求大於等於或小於等於某個數的個數(可以求逆序數)

確定一個數的排名

我把所有的功能整合在了一起了,代碼如下

#include<cstdio>#include<cstdlib>const int inf  = ~0u>>2;#define L ch[x][0]#define R ch[x][1]#define KT (ch[ ch[rt][1] ][0])const int maxn = 500010;int lim;struct SplayTree {int sz[maxn];int ch[maxn][2];int pre[maxn];int rt,top;inline void up(int x){sz[x]  = cnt[x]  + sz[ L ] + sz[ R ];}inline void Rotate(int x,int f){int y=pre[x];ch[y][!f] = ch[x][f];pre[ ch[x][f] ] = y;pre[x] = pre[y];if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;ch[x][f] = y;pre[y] = x;up(y);}inline void Splay(int x,int goal){//將x旋轉到goal的下面while(pre[x] != goal){if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);else   {int y=pre[x],z=pre[y];int f = (ch[z][0]==y);if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);else Rotate(y,f),Rotate(x,f);}}up(x);if(goal==0) rt=x;}inline void RTO(int k,int goal){//將第k位元旋轉到goal的下面int x=rt;while(sz[ L ] != k-1) {if(k < sz[ L ]+1) x=L;else {k-=(sz[ L ]+1);x = R;}}Splay(x,goal);}inline void vist(int x){if(x){printf("結點%2d : 左兒子  %2d   右兒子  %2d   val:%2d sz=%d  cnt:%d\n",x,L,R,val[x],sz[x],cnt[x]);vist(L);vist(R);}}void debug() {puts("");vist(rt);puts("");}inline void Newnode(int &x,int c,int f){x=++top;L = R = 0;pre[x] = f;sz[x]=1; cnt[x]=1;val[x] = c;}inline void init(){ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;rt=top=0; cnt[0]=0;}inline void Insert(int &x,int key,int f){if(!x) {Newnode(x,key,f);Splay(x,0);//注意插入完成後splayreturn ;}if(key==val[x]){cnt[x]++;sz[x]++;Splay(x,0);//注意插入完成後splayreturn ;}else if(key<val[x]) {Insert(L,key,x);} else {Insert(R,key,x);}up(x);}void Del_root(){//刪除根節點int t=rt;if(ch[rt][1]) {rt=ch[rt][1];RTO(1,0);ch[rt][0]=ch[t][0];if(ch[rt][0]) pre[ch[rt][0]]=rt;}else rt=ch[rt][0];pre[rt]=0;up(rt);}void findpre(int x,int key,int &ans){//找前驅節點if(!x)  return ;if(val[x] <= key){ans=x;findpre(R,key,ans);} elsefindpre(L,key,ans);}void findsucc(int x,int key,int &ans){//找後繼節點if(!x) return ;if(val[x]>=key) {ans=x;findsucc(L,key,ans);} elsefindsucc(R,key,ans);}inline int find_kth(int x,int k){ //第k小的數if(k<sz[L]+1) {return find_kth(L,k);}else if(k > sz[ L ] + cnt[x] ) return find_kth(R,k-sz[L]-cnt[x]);else{ Splay(x,0);return val[x];}}int find(int x,int key){if(!x) return 0;else if(key < val[x])  return find(L,key);else if(key > val[x])  return find(R,key);else return x;}int getmin(int x){while(L) x=L;    return val[x];}int getmax(int x){while(R) x=R;   return val[x];}//確定key的排名int getrank(int x,int key,int cur){//cur:當前已知比要求元素(key)小的數的個數if(key == val[x])  return sz[L] + cur + 1;else if(key < val[x])getrank(L,key,cur);else getrank(R,key,cur+sz[L]+cnt[rt]);}int get_lt(int x,int key){//小於key的數的個數 lt:less than if(!x) return 0;if(val[x]>=key) return get_lt(L,key);return cnt[x]+sz[L]+get_lt(R,key);}int get_mt(int x,int key){//大於key的數的個數 mt:more thanif(!x) return 0;if(val[x]<=key) return get_mt(R,key) ;return cnt[x]+sz[R]+get_mt(L,key);}void del(int &x,int f){//刪除小於lim的所有的數所在的節點if(!x) return ;if(val[x]>=lim){del(L,x);} else {x=R; pre[x]=f;if(f==0)  rt=x;del(x,f);}if(x)  up(x);}inline void update(){del(rt,0);}int get_mt(int key) {return get_mt(rt,key);}int get_lt(int key) {return get_lt(rt,key);}void insert(int key) {Insert(rt,key,0);    }void Delete(int key) {int node=find(rt,key);Splay(node,0);cnt[rt]--;if(!cnt[rt])Del_root();}int kth(int k) {return find_kth(rt,k);}int cnt[maxn];int val[maxn];int lim;}spt;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.