ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

平衡树——旋转treap和WBLT

2022-07-13 00:32:44  阅读:219  来源: 互联网

标签:结点 旋转 儿子 叶子 treap WBLT


fhq_treap 和 Splay 之外的平衡树的代码是不可能写的。仅供学术研究,所以只有口胡,没有代码。

  1. 旋转treap

学过 fhq_treap 的都知道 treap 是啥吧(
但是 treap 也可以用旋转来维护。

插入操作:
这是显然的,找到位置插入以后,把结点一路转上去,直到父亲结点的 key 值小于当前结点的 key 值就行了。
容易发现这样旋转没有破坏堆的性质。

删除操作:
如果只有一个儿子那就把儿子转上来,然后到子树进行操作。两个儿子转较小的那个。
配几张图。图中结点处标的都是 key 值。

好的我们要删除 2 这个结点。4<5,把 4 旋转上去。

这样 2 就往下了一些。同理,5<8,把 5 转上去。

只有一个儿子了。只能转 8。

没有儿子结点了。那就可以直接删掉了。

剩下的操作和普通的平衡树就没什么差别了,略。

  1. WBLT

2018年的国集论文里有这个东西。还是非常 interesting 的。
WBLT 全名 Weight Balanced Leafy Tree。Weight Balanced Tree 是大家熟知的,但是这个 Leafy 就比较有趣了。
确切地说,Leafy 是对 BST 进行了一些爆改。
首先这棵树的非叶子结点都有两个儿子。原本的信息都存到叶子结点上,而非叶子结点存储的信息是它的两个儿子的合并。
具体到 WBLT 上,就是非叶子结点的权值和它的右儿子相同。(当然存 size 的时候还是要存子树中有效结点的多少,即叶子结点的个数
但是 BST 的性质还是保留,也就是左子树的叶子结点的值都小于右子树的叶子结点的值。
画个图:

其中 1 2 3 4 就是存储的信息。

接下来我们看这棵树怎么旋转。
还是以上面的树为例,我们做一个左旋,把 4 转上去的操作是这样的:
image
记此时进行旋转的根结点为 x(这里是 4''),左儿子记作 l(x), 右儿子记作 r(x)。
首先我们新建一个结点合并 l(x) 和 l(r(x))。
image
将 l(x) 设为新建的结点。
image
将 r(x) 设为 r(r(x))。
这样就完成了左旋。原来的 r(x) 是不可能被遍历到的,和已经删除无异。(WBLT 中不储存父亲结点)
右旋同理。

然后我们就能用旋转来维护树的平衡了。如果左右子树存储的有效结点个数的比例失调,那么我们就可以通过旋转保持树的平衡。
注:事实上双旋的复杂度才是正确的,但是单旋好像也不容易卡的样子,不过我又不写这个数据结构(

介绍插入删除之前提一嘴,WBLT 的 find 操作和普通的平衡树有一点不一样,那就是要和当前结点的左儿子进行比较,这样才能找到正确的结点。

插入删除:
插入就是递归到叶子结点插进去就行了,然后建立兄弟结点,最后要像线段树一样 pushup 让结点满足 Leafy Tree 的性质。
以上面旋转之后的树为例,我们要插入结点 6。最终结果如下图:
image
事实上我们就是插入了 5,把 4 挪到 5 的兄弟的位置,然后 pushup 的时候把上面的值都改成了 5。
删除也差不多。注意维护好 Leafy Tree 的性质就行。

剩下的操作略,注意结点存的 size 是子树中叶子结点的多少。

标签:结点,旋转,儿子,叶子,treap,WBLT
来源: https://www.cnblogs.com/pjykk/p/16472333.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有