splay tree.GydF4y2Ba
splay树是一种类型GydF4y2Ba二进制搜索树GydF4y2Ba。与其他变体不同GydF4y2BaAVL树GydF4y2Ba, 这GydF4y2Ba红黑树GydF4y2Ba, 或者GydF4y2Ba替罪羊树GydF4y2Ba,splay树并不总是平衡。相反,它被优化,以便最近播放的元素再次迅速访问。GydF4y2Ba
这个属性本质上是类似的GydF4y2Ba堆GydF4y2Ba。堆栈有一流的(LIFO)属性,因此您添加的最新项目是最快的访问。splay树的类似之处在于当您添加新项目时,无论如何都将成为树的根目录。但他们进一步迈出一步。即使只搜索物品,它也成为树的新根。以下GIF显示SPLAY树如何以该顺序插入元素7,3和9。GydF4y2Ba
因为它是一个不平衡的GydF4y2Ba二进制搜索树GydF4y2Ba,splay tree无法保证GydF4y2Ba最差的情况GydF4y2Ba 时间,如平衡二元搜索树可以。平衡二元搜索树具有高度GydF4y2Ba最多GydF4y2Ba 在哪里GydF4y2Ba 是树中的节点数量。所以,Splay树只能保证GydF4y2Ba 摊销GydF4y2Ba时间。GydF4y2Ba
概述GydF4y2Ba
splay树是很像其他二进制搜索树。它们有节点,每个节点都有两个孩子,一个左和一个右。有一个根节点在树的开始时服务。但是,主要区别在于根节点是GydF4y2Ba总是GydF4y2Ba访问的最后一个元素。GydF4y2Ba
如果将元素插入树中,则将旋转树,以便它出现在根位置。此外,如果在树中搜索一个元素,则它将相同的方式移动。GydF4y2Ba
删除是一个主要留给实施者的操作。通常情况下,然而,将被删除的元素是在其右子树的最左边的节点或在其左子树的最右边的节点切换。然后它只是从树上删除。GydF4y2Ba
splay树通常用于树间操作,例如加入,合并,工会和其他GydF4y2Ba放GydF4y2Ba相关数学运算,因为Splay树在这些操作中是有效的。此外,查询高度偏差时使用Splay树。也就是说,当一组查询有利于某个元素时,Splay树是有效的。这是因为频繁查询的元素将出现在树的顶部。例如,如果使用splay树用于存储在商店工作的一组人员,则可能是Manager名称最多的情况。因此,经理的名字将在树顶上花费大部分时间,使其很容易找到。GydF4y2Ba
概念问题GydF4y2Ba
您可以思考设置{1,2,3,4}的插入操作顺序,这些操作将使splay树极其低效?提示:它会使查看的平均案例GydF4y2Ba 像常规一样GydF4y2Ba二进制搜索树GydF4y2Ba。GydF4y2Ba
如果我们以升序插入SET {1,2,3,4},则树本根本不会具有分支因子。splay树看起来像这样。GydF4y2Ba
1 2 3 4 5 6 7GydF4y2Ba4/3 / 2/1GydF4y2Ba
如果我们插入它们,那样是真的GydF4y2Ba下降GydF4y2Ba命令。这棵树只是镜像。GydF4y2Ba
基本操作GydF4y2Ba
splay树支持所有典型的GydF4y2Ba二进制搜索树GydF4y2Ba操作 - 搜索,插入和删除。但是,它是张开树的次操作,这使得所有这些操作成为可能。GydF4y2Ba
张开GydF4y2Ba
splaying是保留splay树的原因GydF4y2Ba大致GydF4y2Ba均衡。要显示节点,请在其上重复执行播放步骤,直到它升到顶部。要决定执行什么样的次数,树看起来三种可能性:GydF4y2Ba
- 节点的父级是根GydF4y2Ba
- 该节点是右侧的左子子(或左子子的右侧的孩子)GydF4y2Ba
- 该节点是左子子的左子子(或右侧儿童的右侧)GydF4y2Ba
如果节点的父级是根,则只需要一个旋转来使其成为根。如果节点是根的左子,则执行正确的旋转,如果节点是根的右侧,则执行左旋转。这与旋转完全相同GydF4y2BaAVL树GydF4y2Ba。这有时被称为“Zig”案例。GydF4y2Ba
如果节点是右侧子的左子,则需要执行两个旋转。让n成为我们尝试扮演的节点,p是它的父级,而g是它的祖父母。它首先旋转n和p右,然后旋转n和g。如果节点是左子子的右侧,则它会相反。它首先旋转n和p左,然后n和g右旋。这有时被称为“Zig-zag”案例。GydF4y2Ba
如果节点是左子子的左子,则还有两个旋转。首先,G和P旋转右转。然后X和P旋转右转。如果节点是右侧的右子,则首先旋转G和P,然后左侧旋转,然后左侧旋转。GydF4y2Ba
这是“Zig-ZAG”案例的示例。圆圈代表树中的节点,它们下面的三角形表示子树。正在访问节点9。首先,它左转左转,7.然后节点9用原来的祖父母12旋转。GydF4y2Ba
所有三种情况都在节点上使用,直到它成为根节点(“Zig”案例是最后一次执行的)。GydF4y2Ba
搜索GydF4y2Ba
在实现SPLAY后,搜索很简单。搜索节点,使用GydF4y2Ba二进制搜索GydF4y2Ba在树下定位节点。然后,在该节点上执行splay以将其带到树的顶部。GydF4y2Ba
插入GydF4y2Ba
要插入节点,请使用二进制搜索在树底部找到其适当位置。然后在该节点上执行splay。GydF4y2Ba
删除GydF4y2Ba
删除是唯一一个为实现者提供一些Wiggle空间的操作。毕竟,当您删除节点时,没有明显的节点。GydF4y2Ba
典型的实现是程序员可以在其右子树中的左子区或左上级节点中使用右上节点删除要删除的节点。然后可以删除节点而不对树的任何后果(因为它没有孩子)。GydF4y2Ba
另一种方式是要删除的节点是首先播放,使其成为根节点。然后它被删除了。我们留下了两个塞列特树木,然后使用加入操作加入在一起,我们将看到GydF4y2Ba之后GydF4y2Ba。GydF4y2Ba
无论如何,典型的实现最终将显示删除节点的父节点。这类似于实施者的自行决定。GydF4y2Ba
额外操作GydF4y2Ba
除了搜索,插入和删除以及促进所有三个的展开,Splay树也有其他操作。由于SPLAY操作,这些操作比在其他树上更快。它们也是Splay树木对软件如此有吸引力的原因之一。GydF4y2Ba
加入GydF4y2Ba
加入两棵树,S和T,使得S中的元素小于T中的所有元素,必须发生两件事。首先,S扮演S中的最大元素。S的根源是S中的最大节点,它没有正确的孩子。其次,将右侧的右子设置为t的根源。得到的树是一个GydF4y2Ba二进制搜索树GydF4y2Ba。GydF4y2Ba
分裂GydF4y2Ba
给定节点,在该节点上拆分一棵树导致两棵树。一棵树具有小于或等于节点的每个元素,另一只元素都具有比节点大的每个元素。首先,我们将在root中扮演节点。然后,我们采取右侧的右手,使其成为自己的树。现在有两棵树满足分裂条件。GydF4y2Ba
渐近复杂性GydF4y2Ba
记住,存在展开树是非常低效的情况下,Splay树的最糟糕的渐近复杂度是线性时间操作。但是,这通常被忽视GydF4y2Ba摊销分析GydF4y2Ba,所以Splay树总是被认为是GydF4y2Ba 时间运营。GydF4y2Ba
也可以看看:GydF4y2Ba大o符号GydF4y2Ba。GydF4y2Ba
手术GydF4y2Ba | 平均数GydF4y2Ba | 最差GydF4y2Ba |
空间GydF4y2Ba | ||
搜索GydF4y2Ba | ||
遍历GydF4y2Ba | *GydF4y2Ba | *GydF4y2Ba |
插入GydF4y2Ba | ||
删除GydF4y2Ba |
*摊销GydF4y2Ba
的优点和缺点GydF4y2Ba
SPLAY TREE的主要优点是它在树顶部保持最疑问的节点,减少后续查询的时间。此引用的本地使得对于编程语言或缓存系统的垃圾收集等系统非常有用。GydF4y2Ba
splay树也具有低的内存开销,类似于GydF4y2Ba替罪羊树GydF4y2Ba。这使得它们对内存敏感程序具有吸引力。GydF4y2Ba
肖像树的最大缺点是它们可以是线性的,我们在观察到GydF4y2Ba概念问题GydF4y2Ba。这对性能非常糟糕,但对于这种情况来说也是非常罕见的。GydF4y2Ba