首先贴贴百度百科对splay树的定义:
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(logn)内完成插入、查找和删除操作。它由丹尼尔·斯立特Daniel Sleator 和 罗伯特·恩卓·塔扬Robert Endre Tarjan 在1985年发明的。在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。
对于搜索树,搜索效率是O(logn),这与树的高度有关,那么如果想要加快树的搜索效率,很明显是要想办法在不改变树的性质的情况下减小树的高度。
考虑这两种情况
以及
无论是第一种树还是第二种树,都满足搜索树的性质,既左子节点均小于父节点,右子节点均大于父节点。
但是由于结构不同,第二种树的高度比第一种要小,即搜索效率第二种比第一种要更优。
因此我们的目标就是找到一种方法,使第一种结构可以转化为第二种结构,以及要防止第二种结构退化成第一种结构。
接下来介绍两种操作
左旋
设当前需要左旋的节点为a,其父节点为b,那么左旋的定义就是将b设为a的左子节点,并将原本a的左子树设为b的右子树。
即如下图所示
右旋
设当前需要右旋的节点为a,其父节点为b,那么右旋的定义就是将b设为a的右子节点,并将原本a的右子树设为b的左子树。
即如下图所示
那么以上两种操作统称为旋转,具体到要使用的时候,就根据节点的位置来选择左旋或者右旋,假如a在b的左子树,那么a就需要右旋,反之亦然。
然后我们尝试一下通过这种旋转操作,将树的高度减少。
将节点1旋转
变成下图所示
然后就惊讶的发现,它的高度没有变化。
但如果先旋转节点2,就会变成下图所示:
这时候高度终于是成功缩小了一层。
所以如果我们要旋转的节点和它上两层的两个父节点形成了一条直线,就需要先旋转其父节点,再旋转它本身。
如果是已经是折线,就直接旋转就行。
因为只有折线的情况有可能经过旋转之后,树的高度会减小。当然并不是所有折线情况,旋转之后都会减少树高,但是还是要尽可能的使树高减小。
理解了上述的操作,也就基本理解了splay树,有错的地方望各位高手指出,代码就不贴出来了,网上基本都有。