Treap模板

真·无旋Treap模板

为了方便地重用代码,C++有了模板和多态功能。

然而OIer一般并不会花时间写这些

(除了我这种实际上已经AFO的人

这个板子喜欢的可以拿去用…出锅了概不负责私信我改awa


码风最早是学习了P3369题解中的红黑树代码,后来参考了GNU STL和自己的偏好,基本固定了写大模板的风格。


再简单讲一讲Treap的思想

Treap是一种基于随机化的自平衡二叉搜索树。为了避免二叉搜索树在精心构造的数据下退化,Treap给每个结点增加了一个随机权值,并设法使随机权值满足堆的性质。将命运掌握在了自己手中

常见的Treap通过插入、删除结点后进行旋转来维持其性质。然而由于Treap的性质简单而容易维护,Treap可以容易地在 O ( l o g 2 n ) O(log_2 n) O(log2n)的时间内分裂成两棵值域不相交的Treap,两棵不相交的Treap也可以在相同时间内合并。

于是国内一位叫做fhq的神仙据此给出了Treap依赖于分裂、合并的一种实现,以牺牲一定运行效率的代价,换取了相对简洁的代码和更加灵活的功能,使得Treap可以维护区间信息。


然而Treap怎么打并不是重点,模板才是。

为了能够在日后日常做题中避免反复打模板,干脆花了一上午敲了一个封装好的板子,也算是锻炼码力。

并且这也是我第一次完全用自己的代码写完普通平衡树

功能和std::set基本相同,实现了一个不可重集合,支持set支持的各类查找操作并支持了查询元素排名和按排名查询(当然效率比起红黑树低一些

一些细小的函数懒得实现,分配器、萃取器啥的麻烦又难搞也没写。尾后迭代器…由于个人能力不足,不得不采用一种丑陋的实现方式,导致空间占用变大…凑合着用吧


代码(底下有说明,代码可以先略过不看)

怎么比我封装好的LCT还长不少

#ifndef TREAP_TEMPLATE //Treap template
#define TREAP_TEMPLATE

#if __cplusplus>=201103L
#include<random>
#endif

#if __cplusplus<201103L
	#ifdef nullptr
		#undef nullptr
	#endif
	#define nullptr NULL
#endif

template<typename _Tp,typename _Cmp=std::less<_Tp>,typename _Alloc=std::allocator<_Tp> >
class treap:_Cmp
{
   
    public:
        typedef _Tp Value_type;
        typedef _Cmp Comparator_type;
        typedef size_t size_type;
        typedef _Alloc alloc_type;
	#if __cplusplus>=201103L
        typedef typename std::allocator_traits<_Alloc> alloc_traits_type;
	#endif
    private:
        struct Node;
        Node *end_node;
        Node *&root;

        inline Node *__get_new_node(_Tp);
        inline void __emplace_node(Node*,_Tp);
        inline void __delete_node(Node*);

        Node *merge(Node*,Node*);
        void split_val(Node*,const _Tp&,Node*&,Node*&);
        void split_val_equal(Node*,const _Tp&,Node*&,Node*&);

		inline static unsigned long long get_pri();
		void destroy_inner_nodes(Node*);

        typedef typename _Alloc::template rebind<Node>::other _node_alloc_type;
	#if __cplusplus>=201103L
        typedef typename alloc_traits_type::template rebind_traits<Node> _node_alloc_traits_type;
	#endif

        _node_alloc_type _node_allocator;
    public:

        struct iterator;

        treap():
            end_node(new Node),
            root(end_node->lc)
        {
   }

		~treap();

        std::pair<iterator,bool> insert(const _Tp&);
        bool erase(const _Tp&);
        iterator begin()const;
        iterator end()const;
        iterator find(const _Tp&)const;
        iterator lower_bound(const _Tp&)const;
        iterator upper_bound(const _Tp&)const;
        iterator find_by_order(const size_type&)const;
        size_type order_of_key(const _Tp&)const;
        size_type size()const;
};

template<typename _Tp,typename _Cmp,typename _Alloc>
struct treap<_Tp,_Cmp,_Alloc>::Node
{
   
    _Tp value;
    unsigned long long pri;
    size_type s;
    Node *lc,*rc,*ftr;
    
	Node():
		pri(get_pri()),
        s(1),
        lc(nullptr),
        rc(nullptr),
        ftr(nullptr)
    {
   }

    Node(_Tp val):
        value(val),
        pri(rand()),
        s(1),
        lc(nullptr),
        rc(nullptr),
        ftr(nullptr)
    {
   }

    void maintain(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值