Treap 树堆 容易实现的平衡树

Treap模板

前几日闲的没事写个平衡树练手,挑个最简单的当然就是Treap,十几分钟大概就可以写出来。

Treap是一棵二叉搜索树(自然满足二叉搜索树的性质),同时节点有一个rand出来的key值,根据这个key值treap同时还是一个堆。

https://baike.baidu.com/item/Treap 这个是百度百科的链接,具体原理可以参考

我们都知道平衡树的调整都需“旋”,但是“旋”这个东西本身比较抽象代码也不直观,这里的实现利用“分割”和“合并”代替了一般平衡树的“旋转”操作
有一个不错的视频可以参考
https://www.bilibili.com/video/av46204315?from=search&seid=9293750279202607136
博客中不再多余赘述,直接看代码就行了

namespace treap{
    int key[maxn],val[maxn],ls[maxn]={0},rs[maxn]={0},_size[maxn]={0};
    int tot=0;
    inline void push_up(int x){
        _size[x]=_size[ls[x]]+_size[rs[x]]+1;
    }
    void Split(int root,int &x,int &y,int v){
        if(root==0){
            x=y=0;
            return;
        }
        if(val[root]<=v) x=root,Split(rs[x],rs[x],y,v);
        else y=root,Split(ls[y],x,ls[y],v);
        push_up(root);
    }
    void Merge(int& root,int x,int y){
        if(x==0||y==0){
            root=x+y;
            return;
        }
        if(key[x]<key[y])root=x,Merge(rs[x],rs[x],y);
        else root=y,Merge(ls[y],x,ls[y]);
        push_up(root);
    }
    void Insert(int &root,int v){
        int x=0,y=0,z=++tot;
        val[z]=v;key[z]=rand();_size[z]=1;
        Split(root,x,y,v);
        Merge(x,x,z);
        Merge(root,x,y);
    }
    void Erase(int &root,int v){
        int x=0,y=0,z=0;
        Split(root,x,y,v);
        Split(x,x,z,v-1);
        Merge(z,ls[z],rs[z]);
        Merge(x,x,z);
        Merge(root,x,y);
    }
    int Kth(int root,int k){
        while(_size[ls[root]]+1!=k){
            if(_size[ls[root]]>=k)root=ls[root];
            else k=k-_size[ls[root]]-1,root=rs[root];
        }
        return val[root];
    }
    int get_Rank(int &root,int v){
        int x=0,y=0;
        Split(root,x,y,v-1);
        int ret=_size[x]+1;
        Merge(root,x,y);
        return ret;
    }
    int Lower(int &root,int v){
        int x=0,y=0;
        Split(root,x,y,v-1);
        int ret=Kth(x,_size[x]);
        Merge(root,x,y);
        return ret;
    }
    int Upper(int &root,int v){
        int x=0,y=0;
        Split(root,x,y,v);
        int ret=Kth(y,1);
        Merge(root,x,y);
        return ret;
    }
}

转载于:https://www.cnblogs.com/zhangxianlong/p/10698033.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值