数据结构 平衡树 Treap讲解

本文详细介绍了Treap树的概念,它是结合了二叉搜索树和堆性质的数据结构。通过示例代码展示了Treap树的基本操作,包括插入、删除、查询等,并提供了详细的解释和参考资料。

累加器传送门:

http://blog.csdn.net/NOIAu/article/details/71775000


以前经常听着lmy大佬说平衡树怎么怎么样,问到一道题怎么做的时候(手写个平衡树就好了啊),觉得好厉害,终于自己学了最简单的平衡树——Treap


首先,Treap,顾名思义就是Tree和heap的结合,也就是具有堆性质的二叉搜索树,好了,想必讲到这里,大家已经完全明白了Treap的原理和实现方法,下面贴上代码


#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 100000+10
using namespace std;

int n,sz,root,ans;

inline const int read(){
   register int x=0,f=1;
   register char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
   while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
   return f*x;
}

inline int rand_num(){
   static int seed=520;
   return seed=int(seed*48271LL%2147483647);
}

struct Treap{
   int lson,rson,val,rnd,size,wei;
}treap[MAXN];

void update(int k){
    treap[k].size=treap[treap[k].lson].size+treap[treap[k].rson].size+treap[k].wei;
}

void Right_Ratote(int &k){
    int t=treap[k].lson;treap[k].lson=treap[t].rson;treap[t].rson=k;
    treap[t].size=treap[k].size;update(k);k=t;
}

void Left_Ratote(int &k){
    int t=treap[k].rson;treap[k].rson=treap[t].lson;treap[t].lson=k;
    treap[t].size=treap[k].size;update(k);k=t;
}
void insert(int &k,int x){
    if(k==0){
        k=++sz;treap[k].size=treap[k].wei=1;
        treap[k].val=x;treap[k].rnd=rand_num();return;
    }
    treap[k].size++;
    if(treap[k].val==x) treap[k].wei++;
    else if(treap[k].val<x){
        insert(treap[k].rson,x);
        if(treap[treap[k].rson].rnd<treap[k].rnd)
        Left_Ratote(k);
    }else{
        insert(treap[k].lson,x);
        if(treap[treap[k].lson].rnd<treap[k].rnd)
        Right_Ratote(k);
    }
}

void del(int &k,int x){
    if(k==0) return;
    if(treap[k].val==x){
        if(treap[k].wei>1){
            treap[k].wei--;
            treap[k].size--;
            return;
        }
        if(treap[k].lson*treap[k].rson==0){
            k=treap[k].lson+treap[k].rson;
        }else if(treap[treap[k].lson].rnd<treap[treap[k].rson].rnd){
            Right_Ratote(k);
            del(k,x);
        }else{
            Left_Ratote(k);
            del(k,x);
        }
    }else if(treap[k].val<x){
        treap[k].size--;
        del(treap[k].rson,x);       
    }else{
        treap[k].size--;
        del(treap[k].lson,x);
    }
}

int query_rank(int k,int x){
    if(!k) return 0;
    if(treap[k].val==x) return treap[treap[k].lson].size+1;
    else if(treap[k].val<x) return treap[treap[k].lson].size+treap[k].wei+query_rank(treap[k].rson,x);
    else return query_rank(treap[k].lson,x);
}

int query_num(int k,int x){
    if(!k) return 0;
    if(x<=treap[treap[k].lson].size) return query_num(treap[k].lson,x);
    else if(x>treap[treap[k].lson].size+treap[k].wei) return query_num(treap[k].rson,x-treap[treap[k].lson].size-treap[k].wei);
    else return treap[k].val;
}

void query_LB(int k,int x){
    if(!k) return;
    if(treap[k].val<x){
        ans=k;
        query_LB(treap[k].rson,x);
    }else{
        query_LB(treap[k].lson,x);
    }
}

void query_UB(int k,int x){
    if(!k) return;
    if(treap[k].val>x){
        ans=k;
        query_UB(treap[k].lson,x);
    }else{
        query_UB(treap[k].rson,x);
    }
}

int main(){
    int opt,x;
    n=read();
    for(register int i=1;i<=n;i++){
       opt=read(),x=read();
       switch(opt){
          case 1:insert(root,x);break;
          case 2:del(root,x);break;
          case 3:printf("%d\n",query_rank(root,x));break;
          case 4:printf("%d\n",query_num(root,x));break;
          case 5:ans=0,query_LB(root,x);printf("%d\n",treap[ans].val);break;
          case 6:ans=0,query_UB(root,x);printf("%d\n",treap[ans].val);break;
       }
    } 
    return 0;
}

这里写图片描述


Ps.给条友链:

http://blog.csdn.net/yang_yulei/article/details/46005845

该博主讲解非常清晰,对我帮助很大


非常感谢zyc大佬的帮助!


Ps.再给条友链,lmy(lemonoil)的平衡树博客也写得很不错

http://blog.csdn.net/lemonoil/article/details/54405613

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值