• 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;
        }
    }
    
  • 相关阅读:
    nginx解决前端跨域配置
    oracle 空表处理
    (转)Oracle修改表空间为自动扩展
    使用silverlight自定义控件时“给定关键字不在字典中”
    arcengine note:
    Jquery CSS 操作
    Jquery Easy-UI 树形菜单的运用
    Easy-UI data-options总结
    数据库 存储过程初探
    ASP.NET 日志的记录(登录日志和异常日志和操作日志)
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10698033.html
Copyright © 2020-2023  润新知