伸展树基本概念
伸展树的基本思想。
伸展树完全是基于局部性原理
(locality)的。
局部性原理
是计算机科学中非常重要的原理,很多设计,比如说多级存储器,缓存,都是基于局部性原理
。简单说来就是<刚访问过的数据,在一段时间内极有可能再次被访问>。因此,对于物理存储器而言,会将刚刚访问过的数据,转移存储到更高级的存储介质中,比如内存或者缓存,以便下次访问这些数据时可以高效地进行。而对于数据结构而言,则可以把刚访问过的数据移动到更容易被访问到的区域,比如列表可以把每次被访问的数据都交换到列表的头部,这就构成了自调整列表。
伸展树也是同样的思想,即对于一棵二叉搜索树而言,将刚刚被访问的数据移动到树根结点,从而使得后续的访问可以高效地找到该数据。
伸展树和AVL树的比较。
伸展树也是一棵平衡二叉搜索树,但是可以看到,伸展树和AVL树
有很大的差异。
前面我们说,对于任意一种平衡二叉搜索树,都是关注两个方面的问题,即平衡条件,以及失衡后的调整算法。因此,AVL树
引入了一个平衡因子来作为它的平衡条件,并且失衡调整算法也都是围绕这个平衡因子而展开。但是,从前面伸展树的思想可以看出,伸展树没有所谓的平衡条件,因此它不需要维护任何额外的信息,包括树的高度。它只是在每次对某结点的访问后,将该结点移动到树根,并且同时对树的结构进行调整,就这样实现了它的平衡。
因此相较而言,AVL树
更像是循规蹈矩,如履薄冰。而伸展树则更加潇洒,不顾小节。
伸展策略
那么实现伸展树就比较简单了,只需要将被访问结点移动到根结点就可以了,所以应该怎么移动呢?
逐层伸展策略。
一个很简单的思想是找到被访问的结点后,不断地将该结点与它的父结点进行单旋转,直到该结点被旋转到根结点。
这种策略固然是可行的,但是在最坏情况下,它拥有比较差的时间性能,如下图所示:
对于这种一开始就呈现单链结构的搜索树,设它具有n个结点,如果每次都访问它深度最深的那个结点,那么每次被访问结点的深度为 n − 1 , n − 2 , . . . . , 3 , 2 , 1 , 0 n-1, n-2, ...., 3, 2, 1, 0 n−1,n−2,....,3,2,1,0,所以一个周期这样的访问累计需要 Ω ( n 2 ) \Omega(n^2) Ω(n2)的时间,分摊时间复杂度为 Ω ( n ) \Omega(n) Ω(n)。这个结果已经与列表这种线性结构相当了,所以很难可以让人满意。
双层伸展策略。
双层伸展策略只是逐层伸展策略的一个推广,它们之间的差别其实非常小,但是对性能却有一个质的提升。据邓公所说,双层伸展策略其实就是逐层伸展这条龙上点出的<睛>,而在这之前,逐层伸展这样一个整体的龙的结构是已经具备了的。
双层伸展策略,顾名思义,就是每次伸展时都以两个单位向上层追溯,而不是逐层伸展的一个单位。所以,这就需要反复考察祖孙三代 g , p , v g, p ,v g,p,