【学习笔记】Size-Balanced Tree(SBT)

零、前言

以学习为借口,是不做题摆烂的最好方式。毕竟 SBT \textit{SBT} SBT 在我的 O I \rm OI OI 生涯里就没使用过。今天才学的说。参考原论文,但是纯英文。

壹、怎么平衡

利用一个比较奇葩的性质,侄子子树大小更小。写成式子即 size ( x . lson . lson/rson ) ⩽ size ( x . rson ) \text{size}(x.\text{lson}.\text{lson/rson})\leqslant\text{size}(x.\text{rson}) size(x.lson.lson/rson)size(x.rson),对于另一侧也成立。

然后即可证明树高是 O ( log ⁡ n ) \mathcal O(\log n) O(logn) 的。需要逆向思考一下,记 f ( h ) f(h) f(h) 为高度为 h h h SBT \text{SBT} SBT 至少需多少个节点。不妨设左儿子高度为 ( h − 1 ) (h{-}1) (h1),根据性质,右儿子至少大小为 f ( h − 2 ) f(h{-}2) f(h2),所以有
f ( h ) ⩾ f ( h − 1 ) + f ( h − 2 ) + 1 f(h)\geqslant f(h{-}1)+f(h{-}2)+1 f(h)f(h1)+f(h2)+1

初值 f ( 1 ) = 1 ,    f ( 2 ) = 2 f(1)=1,\;f(2)=2 f(1)=1,f(2)=2 易知。显然这是指数级增长,故树高 O ( log ⁡ n ) \mathcal O(\log n) O(logn)

顺便聊两句:发明者本人声称 SBT \text{SBT} SBT 不属于 Weight Balanced Tree \text{Weight Balanced Tree} Weight Balanced Tree

贰、怎么维护平衡

记方法 maintain ( x ) \texttt{maintain}(x) maintain(x) 为,通过 旋转 使得 x x x 的子树为 SBT \text{SBT} SBT 。具体调整方法可见原论文,因为其中附有图片。直观来说就是将 size \text{size} size 过大的侄子子树旋转到高处。

下面给出代码。不存储父节点,类似于自顶向下旋转,故 rotate \texttt{rotate} rotate 函数非常简单。

void rotate(Node* &o, int d){
	Node* const k = o->ch[d];
	o->ch[d] = k->ch[d^1], k->ch[d^1] = o;
	k->size = o->size, o->pushUp(), o = k;
}
/// @brief check for lighter part
void maintain(Node* &o, int d){
	if(o->ch[d^1]->ch[d^1]->size > o->ch[d]->size) rotate(o,d^1);
	else if(o->ch[d^1]->ch[d]->size > o->ch[d]->size)
		rotate(o->ch[d^1],d), rotate(o,d^1); else return;
	maintain(o->ch[0],1), maintain(o->ch[1],0);
	maintain(o,0), maintain(o,1);
}

至于为什么它是对的,那就是子树已经 BST \text{BST} BST 了,放缩一下可知。不想深究,能用就行。注意:空节点应为分配了内存的特殊地址,即 Node* _null 为自定义值。

insert \texttt{insert} insert 时,要自顶向上 maintain \texttt{maintain} maintain 。而 erase \texttt{erase} erase 的实现方式是,若删去点不是叶子结点,就递归删除左子树的最大值(或删去右子树最小值),然后放到该节点上,最后 maintain \texttt{maintain} maintain

一个有趣的事情是, erase \texttt{erase} erase 之后不 maintain \texttt{maintain} maintain 的复杂度仍然正确:均摊复杂度变为 O ( log ⁡ ∣ insert ∣ ) \mathcal O(\log|\text{insert}|) O(loginsert)

叁、时间复杂度

Φ = ∑ i ∈ T depth ( i ) \Phi=\sum_{i\in T}\text{depth}(i) Φ=iTdepth(i),可以发现 maintain \texttt{maintain} maintain 中的 rotate \texttt{rotate} rotate 会使得 Φ \Phi Φ 至少减少 1 1 1

Φ \Phi Φ 只在 insert \texttt{insert} insert 时增加树高 O ( log ⁡ n ) \mathcal O(\log n) O(logn),故 rotate \texttt{rotate} rotate 复杂度可以均摊到 insert \texttt{insert} insert 操作上,而后 maintain \texttt{maintain} maintain 是均摊 O ( 1 ) \mathcal O(1) O(1) 的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值