FHQ-Treap小结
$Orz$ 范浩强大爷,竟然搞出了如此夺天地造化的数据结构.
$FHQ-Treap$,又名非旋$Treap$,是范浩强大爷在某些奇特的灵感之下发明的一种平衡树,因其与$Treap$相似的性质和无旋转操作的特性被称为非旋$Treap$.非旋$Treap$用$Split$和$merge$两个操作维护平衡,其本质是堆的合并.(左偏树?)
前置函数&结构体:
1 |
|
我们先来介绍一下$FHQ-Treap$的灵魂之一:$Split$操作
$Split(rt,k)$ 表示把以 $rt$ 为根的树中的前$k$个元素分裂出来,其返回值为一个二元组表示分裂出来的两棵树的根
也十分好写
$Code:$
1 | inline Drt Split (Treap * rt , int k) { |
这样,就完成了$Split$ 操作.
再来看$merge$ 操作
$merge(x,y)$ 表示把以$x$为根的树和以$y$为根的树合并,返回值为新树的根
也并不难写
$Code:$
1 | inline Treap * merge (Treap * x , Treap * y) { |
这就是非旋$Treap$的两个核心操作,当然还有一些比较重要的基础操作,直接放上吧,也不难写
$Getrank(rt,key)$ 表示在以$rt$为根的树中查询$key$的排名(名次树功能之一)
1 | inline int Getrank (Treap * rt , int key) { |
$Getkth(rt,key)$表示在以$rt$为根的子树中查询排名为$key$的元素(名次树功能之二)
1 | inline int Getkth (Treap * & rt , int key) { // 这里有对根的修改 |
$insert(rt,key)$表示在以$rt$为根的树中插入$key$这个元素
1 | inline void insert (Treap * & rt , int key) { |
$remove(rt,key)$表示在以$rt$为根的树中删除$key$这个元素
1 | inline void remove (Treap * & rt , int key) { |
前驱和后继也比较简单
前驱就是:
1 | Getkth ( root , Getrank ( root , key ) ) ; |
后继就是:
1 | Getkth ( root , Getrank ( root , key + 1 ) + 1 ) |
这几个相信各位一看就懂,也就不再赘述了.
我个人认为$FHQ-Treap$是最容易理解的平衡树,而且码量也较小,很适合像博主这样的蒟蒻学习.
$Added$ :
最近又发现了 $FHQTreap$ 的另一种 $Split$ 的方式:按权值分裂
就是把整棵树按照权值分裂成一半比 $key$ 大的,一半比 $key$ 小的
有的时候,这种分裂有奇效
$Code$ :
1 | inline Drt SplitV ( Treap * rt , int key ) { |