ACM算法总结 数据结构(四)(pb_ds库)




简介

pb_ds 全称为 Policy-Based Data Structures,里面定义了很多比 STL 更实用的数据结构,直接好处就是比如你要用一个 Treap 去维护某些数据,本来要写几十行的 Treap,现在只用几行代码就可以定义一个这样的结构出来。

使用 pb_ds 需要的头文件以及一些命名空间的申明:

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#define ext __gnu_pbds
using namespace ext;

或者可以直接:

#include <bits/extc++.h>

这样后面的数据结构需要的额外头文件都可以不用管了。




Hash表

有两种 hash表的写法:

ext::cc_hash_table<int,bool> h1;    // 拉链法 
ext::gp_hash_table<int,bool> h2;    // 探查法

都重载了 [] 运算符,速度跟 unordered_map 可能差不多。




Heap

和标准 STL 一样也是 priority_queue,不过它有很多种实现方式,也就是可以通过不同的标签(tag)指定不同的实现方式。使用 pb_ds 的 priority_queue 需要包含头文件:

#include <ext/pb_ds/priority_queue.hpp>

定义方式为:

priority_queue<type,cmp=std::less<type>,tag=pairing_heap_tag>

具体来说有如下几种tag:

ext::priority_queue<int,greater<int> > que1;                    // (默认为配对堆)
ext::priority_queue<int,greater<int>,pairing_heap_tag> que2;    // 配对堆(应该是最快的)
ext::priority_queue<int,greater<int>,binary_heap_tag> que3;     // 二叉堆
ext::priority_queue<int,greater<int>,binomial_heap_tag> que4;   // 二项堆
ext::priority_queue<int,greater<int>,rc_binomial_heap_tag> que5;// 
ext::priority_queue<int,greater<int>,thin_heap_tag> que6;       // 斐波那契堆

pb_ds 的 priority_queue 的基本操作例如 poppushtopsize 等等和 STL 的是一样的,所以一般情况下用 STL 的 priority_queue 就足够了,但是 pb_ds 的有一个操作非常好,就是 que.join(priority_queue &q),该操作可以合并两个堆,并且把被合并的堆清空,这就完美地解决了可并堆的问题。




Tree

这个是我认为目前来说 pb_ds 最有用的地方了,总是会有需要维护一堆数据,然后查询其中排名啊什么的,这个用 Treap(或者类似的 Splay 树)当然可以解决,但是 pb_ds 已经帮我们实现了红黑树,并且支持查询排名等等扩展功能。

需要的额外头文件:

#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

定义方法:

tree<type,null_type,cmp,tag,update>

不过一般只会用到这个:

typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;

其中 tag 其实还有其他的实现方式(例如splay等等),但是据 codeforces 这篇博客说的其它实现方式的某些操作是线性复杂度的,所以最好就用红黑树了。这个 oset 的基本操作和 STL 的 set 一样,但是它支持下面两个有用的操作:

oset.find_by_order(x)   // 返回一个迭代器,指向排名为x(从0开始)的元素
oset.order_of_key(x)    // 返回严格小于x的元素数目,也就是x的排名(从0开始)

尽管非常有用,但是它和 set 一样,不能处理重复元素,所以手写 Treap 还是有用的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值