Splay Tree——动机和宏观策略 (2)

我们还要另找方法——在初始访问路径上进行一些神奇的旋转,只用了O(1)的空间,而且保持O(logN的时间复杂度

 

具体而言就是:双层伸展,向上追溯两层,通过两次旋转把被访问节点上移至祖父的位置,而且!不是像之前一样自下而上伸展,而是自顶向下进行伸展。这可以说是SplayTree的点睛之笔。这是在1985年Tarjan大神的一篇论文Self-adjusting binary search trees里提出来的(和他有关的还有一个Tarjan算法,是关于图的连通性的神奇算法)。他们的相对位置无非四种:之字型两种,一字型两种。

 

Splay Tree——动机和宏观策略

 子孙异侧

先从这个情况说起,从难啃的骨头开始。有些书上会把这种情况称为“之字形”,以此为例:

Splay Tree——动机和宏观策略

“这特么不就是双旋转么,而且这也就是逐层伸展两次而已,没什么实质区别啊(摔)”,的确是这样,这个部分区别不大。但重点在于另外这条龙一只眼睛才是闪光之处。

 

子孙同侧

有些书上也称为“一字形”。我们先看一下逐层伸展的调整过程,然后和Tarjan的策略作一比较,就知道差距有多大了。

Splay Tree——动机和宏观策略

 

这是我们凡人想到的方法。下面是Tarjan的点睛之笔:

Splay Tree——动机和宏观策略

 

这里的重中之重是:需要首先越级,从祖父而不是父节点来开始旋转,具体来说就是,经过祖父节点的一次左-左旋转,节点p以及v都会上升一层。接下来对新的树根也就是p,再做一次左-左旋转,把v拉上来成为树根,Done。把这两种方法作一对比,emmm好像没什么大差别啊,是吧?的确这里面的神奇之处一时半会难以察觉,看起来反正都是提高了两层倍,

毕竟在局部拓扑结构上还是有微妙的差异,更重要的是——这种局部的微妙差异将导致全局的不同,而且那种不同将是根本性的、颠覆性的!Splay树在这个伸展方式的革命中失去的只是锁链,他们获得的将是整个世界。

 

现在来看看这个差异所带来的利好。如果用这种方式我们再来访问最深的节点,会有什么改进呢? 

Splay Tree——动机和宏观策略

 

现在的改进在于每一层能挂更多的节点了,这就是有效控制树高的一个方法。之前说的逐层伸展最坏情况之所以“坏”是因为,尽管能调整到树根,但是在这个过程中树的高度会以算术级数的速度急剧膨胀,这是一种不计后果的方法,所以很坏。而Tarjan的方法优越性在于,在每次即使访问最深的节点时候,也能控制树高,渐进意义上是之前逐层伸展树高的一半,记得前面说的“会导致全局的不同”么,就是这里的树高缩减一半!这个特性太好了,节点越多,访问次数越多,这个控制的效果越明显,这也被称为SplayTree的折叠效果。那么总结一下双层伸展的核心优势——

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzfjs.html