现在的位置: 首页 > 综合 > 正文

伸展树-splay

2018年05月02日 ⁄ 综合 ⁄ 共 986字 ⁄ 字号 评论关闭

http://hi.baidu.com/yangchenhao/item/02a818ed75ecf2245a2d64a1

splay作为一个二叉排序树所具有特点用一句来概述就是“可以让你把指的结点放在树根的位置或者作为树根的儿子”很多参考资料都会这么介绍 splay 说它是一个自调整树,把最近访问的节点移到根处以使得下次再访问它时可以快速找到,我理解的 splay 就只有一种操作就是把一个节点移动到根处,在这个过程中我们不需要处理平衡的问题,尽管它可能会变成一个线性的形状但这都是小概率事件

就我目前的知识而言 splay 强大之处在于对它可以快速的对区间进行操作,比如对一个序列的指定子序列进行反转或者把它们整体移动到一个新的位置(参考TOJ-3578).。还对在区间的指定位置处随意插入、删除、更新元素,同时可以很快取得指定子区间的和、指定子区间的连续或者区间内的最大、最小值(参考SPOJ-4487)

初看起来询问区间最大最小值与子区间和或者连续最大和 这些不都是线段树干的活。是的你没有想错,在学会 splay 之前,线段树的确是处理这个区间问题的高手,但在你完全掌握 splay 后,它能让你处理更多的区间操作,对一些问题它内功要远远高于线段树,至于一些复杂问题都到了非用它不可的地步。

说了这么多废话现在来说说它的魅力之处吧:假设你已经知道二叉查找树的左右旋转操作,那么你一定可以
把树中指定的一个节点旋转到根部,这就是 splay 的看家本领,别的扩展功能全依靠它了。先说下如何在一个指定的位置插入一个值,假设有数列 1,2,3,4,5,6,7为元素的 splay树,如果我们要在第3个位置 与第4个位置(即3与4)之间插入一个值为 val 的新元素 应该进行的操作是:
(1)把元素3旋转到根处。
(2)把元素4旋转到根节点下面即作为3的儿子。
这时4一定是3的右儿子,并且它的左子是空的,现在就新建一个以 val 为值的新元素挂在根的右子的左子上面(不明白的动手画下图)。现在如果对 splay 树进行中序遍历的话是不是发现 val 已经在 3 与4之间了。

同样的道理可以把一个新区间插入一个指定的位置上或者把一个指定的值与指的区间删除,方法都是进行两个旋转然后要被处理的元素或者区间就神奇地程现在根的右子的左子那里,如果还有其它的统计信息可以记录在相应的区间的根处,当 splay 操作对它进行旋转时注意实时更新就可以了

【上篇】
【下篇】

抱歉!评论已关闭.