平衡树代码总结

Posted robin20050901

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树代码总结相关的知识,希望对你有一定的参考价值。

这里给出博主的几种平衡树模板代码

vector

代码:

// luogu-judger-enable-o2
#include<bits/stdc++.h>

#define rd(x) x=read()

using namespace std;

int n;
vector<int>v;

inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}

int main()
{
    rd(n);
    for(int i=1;i<=n;i++)
    {
        int opt,x;
        rd(opt),rd(x);
        if(opt==1)v.insert(upper_bound(v.begin(),v.end(),x),x);
        else if(opt==2)v.erase(lower_bound(v.begin(),v.end(),x));
        else if(opt==3)printf("%d
",lower_bound(v.begin(),v.end(),x)-v.begin()+1);
        else if(opt==4)printf("%d
",v[x-1]);
        else if(opt==5)printf("%d
",*--lower_bound(v.begin(),v.end(),x));
        else if(opt==6)printf("%d
",*upper_bound(v.begin(),v.end(),x));
    }
    return 0;
}

Treap:

// luogu-judger-enable-o2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>

#define rd(x) x=read()
#define N 100005
#define inf (1<<30) 

using namespace std;

inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}

int q;
int ncnt,root;
struct T{
    int s,v,cnt,rnd,ch[2];
}t[N];

void pushup(int rt){t[rt].s=t[t[rt].ch[0]].s+t[t[rt].ch[1]].s+t[rt].cnt;}

void rotate(int &rt,int d)
{
    int k=t[rt].ch[d^1];
    t[rt].ch[d^1]=t[k].ch[d];
    t[k].ch[d]=rt;
    pushup(rt),pushup(k);
    rt=k;
}

void ins(int &rt,int x)
{
    if(!rt)
    {
        rt=++ncnt,t[rt].s=t[rt].cnt=1,t[rt].v=x,t[rt].rnd=rand();
        return ;
    }
    if(t[rt].v==x){t[rt].cnt++,t[rt].s++;return ;}
    int d=(x>t[rt].v);
    ins(t[rt].ch[d],x);
    if(t[rt].rnd<t[t[rt].ch[d]].rnd)rotate(rt,d^1);
    pushup(rt);
}

void del(int &rt,int x)
{
    if(!rt)return;
    if(x<t[rt].v)del(t[rt].ch[0],x);
    else if(x>t[rt].v)del(t[rt].ch[1],x);
    else
        if(t[rt].ch[0])
            if(t[rt].ch[1])
            {
                int d=(t[t[rt].ch[0]].rnd>t[t[rt].ch[1]].rnd);
                rotate(rt,d);
                del(t[rt].ch[d],x);
            }
            else
            {
                rotate(rt,1);
                del(t[rt].ch[1],x);
            }
        else
            if(t[rt].ch[1])
            {
                rotate(rt,0);
                del(t[rt].ch[0],x);
            }
            else
            {
                t[rt].cnt--,t[rt].s--;
                if(!t[rt].cnt)rt=0;
            }
    pushup(rt);
}

int rank(int rt,int x)
{
    if(!rt)return 0;
    if(t[rt].v==x)return t[t[rt].ch[0]].s+1;
    else if(t[rt].v<x)return t[t[rt].ch[0]].s+t[rt].cnt+rank(t[rt].ch[1],x);
    else return rank(t[rt].ch[0],x);
}

int find(int rt,int x)
{
    if(!rt)return 0;
    if(t[t[rt].ch[0]].s>=x)return find(t[rt].ch[0],x);
    else if(t[t[rt].ch[0]].s+t[rt].cnt<x)return find(t[rt].ch[1],x-t[rt].cnt-t[t[rt].ch[0]].s);
    else return t[rt].v;
}

int pre(int rt,int x)
{
    if(!rt)return -inf;
    if(t[rt].v>=x)return pre(t[rt].ch[0],x);
    else return max(t[rt].v,pre(t[rt].ch[1],x));
}

int suc(int rt,int x)
{
    if(!rt)return inf;
    if(t[rt].v<=x)return suc(t[rt].ch[1],x);
    else return min(t[rt].v,suc(t[rt].ch[0],x));
}

int main()
{
    rd(q);
    while(q--)
    {
        int opt,x;
        rd(opt),rd(x);
        if(opt==1)ins(root,x);
        else if(opt==2)del(root,x);
        else if(opt==3)printf("%d
",rank(root,x));
        else if(opt==4)printf("%d
",find(root,x));
        else if(opt==5)printf("%d
",pre(root,x));
        else printf("%d
",suc(root,x));
    }
    
    return 0;
}

Splay

// luogu-judger-enable-o2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>

#define rd(x) x=read()
#define N 100005

using namespace std;

int q;
int ncnt,root;
struct T{
    int s,v,cnt,fa,ch[2];
}t[N];

inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}

int chk(int rt){return t[t[rt].fa].ch[1]==rt;}

int pushup(int rt){return t[rt].s=t[t[rt].ch[0]].s+t[t[rt].ch[1]].s+t[rt].cnt;}

void rotate(int x)
{
    int y=t[x].fa,z=t[y].fa,k=chk(x),w=t[x].ch[k^1];
    t[y].ch[k]=w,t[w].fa=y;
    t[z].ch[chk(y)]=x,t[x].fa=z;
    t[x].ch[k^1]=y,t[y].fa=x;
    pushup(y),pushup(x);
}

void splay(int x,int goal=0)
{
    while(t[x].fa!=goal)
    {
        int y=t[x].fa,z=t[y].fa;
        if(z!=goal)
        {
            if(chk(x)==chk(y))rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    if(!goal)root=x;
}

void ins(int x)
{
    int rt=root,pos=0;
    while(rt&&t[rt].v!=x)pos=rt,rt=t[rt].ch[x>t[rt].v];
    if(rt)t[rt].cnt++;
    else
    {
        rt=++ncnt; 
        if(pos)t[pos].ch[x>t[pos].v]=rt;
        t[rt].ch[0]=t[rt].ch[1]=0;
        t[rt].fa=pos,t[rt].v=x;
        t[rt].cnt=t[rt].s=1;
    }
    splay(rt);
}

void find(int x)
{
    int rt=root;
    while(t[rt].ch[x>t[rt].v]&&t[rt].v!=x)rt=t[rt].ch[x>t[rt].v];
    splay(rt);
}

int rank(int k)
{
    int rt=root;
    while("zth loves msy")
    {
        if(t[rt].ch[0]&&k<=t[t[rt].ch[0]].s)rt=t[rt].ch[0];
        else if(k>t[t[rt].ch[0]].s+t[rt].cnt)k-=t[t[rt].ch[0]].s+t[rt].cnt,rt=t[rt].ch[1];
        else return rt;	 
    }
}

int pre(int x)
{
    find(x);
    if(t[root].v<x)return root;
    int rt=t[root].ch[0];
    while(t[rt].ch[1])rt=t[rt].ch[1];
    return rt;
}

int suc(int x)
{
    find(x);
    if(t[root].v>x)return root;
    int rt=t[root].ch[1];
    while(t[rt].ch[0])rt=t[rt].ch[0];
    return rt;
}

void del(int x)
{
    int last=pre(x),next=suc(x);
    splay(last),splay(next,last);
    int _del=t[next].ch[0];
    if(t[_del].cnt>1)
    {
        t[_del].cnt--;
        splay(_del);
    }
    else t[next].ch[0]=0;
} 

int main()
{
    rd(q);
    ins(0x3f3f3f3f),ins(0xcfcfcfcf);
    while(q--)
    {
        int opt,x;
        rd(opt),rd(x);
        if(opt==1)ins(x);
        else if(opt==2)del(x);
        else if(opt==3){find(x);printf("%d
",t[t[root].ch[0]].s);}
        else if(opt==4)printf("%d
",t[rank(x+1)].v);
        else if(opt==5)printf("%d
",t[pre(x)].v);
        else printf("%d
",t[suc(x)].v);
    }
    
    return 0;
}

替罪羊树

// luogu-judger-enable-o2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>

#define rd(x) x=read()
#define N 100005

using namespace std;

struct T{
    int s,f,v,d,ch[2];
}t[N];
int ncnt,root,cnt;
int Lrd[N],r[N];
int n;
const double p=0.75;


inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}

void init(int rt)
{
    t[rt].s=t[rt].f=1;
    t[rt].ch[0]=t[rt].ch[1]=0;
}

bool bal(int rt){return (double)t[rt].f*p>(double)max(t[t[rt].ch[0]].f,t[t[rt].ch[1]].f);} 

void lrd(int rt)
{
    if(!rt)return;
    lrd(t[rt].ch[0]);
    if(t[rt].d)Lrd[++cnt]=rt;
    lrd(t[rt].ch[1]);
}

void pushup(int rt)
{
    t[rt].s=t[t[rt].ch[0]].s+t[t[rt].ch[1]].s+1; 
    t[rt].f=t[t[rt].ch[0]].f+t[t[rt].ch[1]].f+1;
}

void setup(int &rt,int l,int r)
{
    int mid=(l+r)>>1;
    rt=Lrd[mid];
    if(l==r){init(rt);return;}
    if(l<mid)setup(t[rt].ch[0],l,mid-1);
    else t[rt].ch[0]=0;
    setup(t[rt].ch[1],mid+1,r);
    pushup(rt);
}

void rebuild(int &rt)
{
    cnt=0;
    lrd(rt);
    if(cnt)setup(rt,1,cnt);
    else rt=0;
}

void check(int rt,int v)
{
    int k=(v>t[rt].v);
    while(t[rt].ch[k])
    {
        if(!bal(t[rt].ch[k]))
        {
            rebuild(t[rt].ch[k]);
            return ;
        }
        rt=t[rt].ch[k];
        k=(v>t[rt].v);
    }
}

void ins(int &rt,int x)
{
    if(!rt)
    {
        rt=++ncnt,t[rt].v=x,t[rt].d=1,init(rt);
        return ;
    }
    t[rt].s++,t[rt].f++;
    if(x<=t[rt].v)ins(t[rt].ch[0],x);
    else ins(t[rt].ch[1],x);
}

int rank(int x)
{
    int rk=1,rt=root;
    while(rt) 
    {
        if(t[rt].v>=x)rt=t[rt].ch[0];
        else rk+=t[t[rt].ch[0]].f+t[rt].d,rt=t[rt].ch[1];
    }
    return rk;
}

int find(int x)
{
    int rt=root;
    while(rt)
    {
        if(t[rt].d&&t[t[rt].ch[0]].f+1==x)return t[rt].v;
        else if(t[t[rt].ch[0]].f>=x)rt=t[rt].ch[0];
        else x-=t[rt].d+t[t[rt].ch[0]].f,rt=t[rt].ch[1];
    }
}

void del(int &rt,int rk)
{
    if(t[rt].d&&t[t[rt].ch[0]].f+1==rk)
    {
        t[rt].d=0;
        t[rt].f--;
        return ;
    }
    t[rt].f--;
    if(t[t[rt].ch[0]].f+t[rt].d>=rk)del(t[rt].ch[0],rk);
    else del(t[rt].ch[1],rk-t[rt].d-t[t[rt].ch[0]].f);
}

void Del(int x)
{
    del(root,rank(x));
    if((double)t[root].s*p>(double)t[root].f)rebuild(root);
}
 
int main()
{
    rd(n);
    while(n--)
    {
        int opt,x;
        rd(opt),rd(x);
        if(opt==1)ins(root,x),check(root,x);
        else if(opt==2)Del(x);
        else if(opt==3)printf("%d
",rank(x));
        else if(opt==4)printf("%d
",find(x));
        else if(opt==5)printf("%d
",find(rank(x)-1));
        else printf("%d
",find(rank(x+1)));
    }
    
    return 0;
}

FHQ treap

// luogu-judger-enable-o2
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>

#define rd(x) x=read()
#define N 100005

using namespace std;

int n;
int ncnt;
struct T{
    int v,rnd,s,ch[2];
}t[N];

inline int read()
{
    int f=1,x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();}
    return x*f;
}

void update(int rt){t[rt].s=t[t[rt].ch[0]].s+t[t[rt].ch[1]].s+1;}

int NewNode(int v)
{
    t[++ncnt].s=1;
    t[ncnt].v=v;
    t[ncnt].rnd=rand();
    return ncnt;
}

int merge(int x,int y)
{
    if(!x||!y) return x+y;
    if(t[x].rnd<t[y].rnd)
    {
        t[x].ch[1]=merge(t[x].ch[1],y);
        update(x);
        return x;
    }
    else
    {
        t[y].ch[0]=merge(x,t[y].ch[0]);
        update(y);
        return y;
    }
}

void split(int rt,int pos,int &l,int &r)
{
    if(!rt)l=r=0;
    else
    {
        if(t[rt].v<=pos)
        {
            l=rt;
            split(t[rt].ch[1],pos,t[rt].ch[1],r);
        }
        else
        {
            r=rt;
            split(t[rt].ch[0],pos,l,t[rt].ch[0]);
        }
        update(rt);
    }
}

int kth(int rt,int pos)
{
    while(1)
    {
        if(pos<=t[t[rt].ch[0]].s)rt=t[rt].ch[0];
        else if(pos==t[t[rt].ch[0]].s+1) return rt;
        else
        {
            pos-=t[t[rt].ch[0]].s+1;
            rt=t[rt].ch[1];
        }
    }
}

int main()
{
    srand(time(0));
    rd(n);
    int root=0,x,y,z;
    while(n--)
    {
        int opt,a;
        rd(opt),rd(a);
        if(opt==1)
        {
            split(root,a,x,y);
            root=merge(merge(x,NewNode(a)),y);
        }
        else if(opt==2) 
        {
            split(root,a,x,z);
            split(x,a-1,x,y);
            y=merge(t[y].ch[0],t[y].ch[1]);
            root=merge(merge(x,y),z);
        }
        else if(opt==3)
        {
            split(root,a-1,x,y);
            printf("%d
",t[x].s+1);
            root=merge(x,y);
        }
        else if(opt==4)printf("%d
",t[kth(root,a)].v);
        else if(opt==5) 
        {
            split(root,a-1,x,y);
            printf("%d
",t[kth(x,t[x].s)].v);
            root=merge(x,y);
        }
        else if(opt==6)
        {
            split(root,a,x,y);
            printf("%d
",t[kth(y,1)].v);
            root=merge(x,y);
        }
    }
    
    return 0;
}

以上是关于平衡树代码总结的主要内容,如果未能解决你的问题,请参考以下文章

数据结构-- 平衡树

平衡树学习小记

平衡二叉树的旋转类型及代码实现

树-概念性总结及代码示例

学习数据结构笔记(12) --- [平衡二叉搜索树(AVLTREE)]

树总结(二)平衡二叉树