Data Structures Algorithms 简明教程

Splay Trees

Splay 树是二叉搜索树的变体,因为它包含所有 BST 操作,如插入、删除和搜索,然后是另一个称为 splaying 的扩展操作。

例如,一个值“A”应该被插入到树中。如果树为空,则将“A”添加到树的根并退出;但是如果树不为空,则使用二分查找插入操作来插入元素,然后对新节点执行 splaying。

类似地,在 splay 树中搜索一个元素之后,包含该元素的节点也必须被 splaying。

但是我们如何执行 splaying?简单来说,splaying 就是将一个操作节点移到根处的过程。它有六种类型的旋转。

  1. Zig rotation

  2. Zag rotation

  3. Zig-Zig rotation

  4. Zag-Zag rotation

  5. Zig-Zag rotation

  6. Zag-Zig rotation

Zig rotation

当操作节点是根节点或根节点的左子节点时,执行 zig 旋转。该节点向右旋转。

Zig rotation

经过移动后,树看起来如下:

after shift

Zag rotation

当操作节点是根节点或根节点的右子节点时,也执行 zag 旋转。该节点向左旋转。

Zag rotation

经过移动后,操作节点变为根节点:

root node

Zig-Zig rotation

当操作节点同时具有父节点和祖先节点时,执行 zig-zig 旋转。该节点向右移动两个位置。

Zig Zig rotation

第一次旋转将树向右移动一个位置:

root node 5

第二次向右旋转将再次将节点移动一个位置。移动后的最终树看起来如下:

root node 3

Zag-Zag rotation

当操作节点同时具有父节点和祖先节点时,也执行 zag-zag 旋转。该节点向左移动两个位置。

Zag Zag rotation

经过第一次旋转后,树看起来如下:

after first rotation

然后,第二次旋转后的最终树如下所示。然而,操作节点仍然不是根,因此 splaying 被认为不完整。因此,在这种情况下再次应用其他合适的旋转,直到该节点成为根节点。

after second rotatios

Zig-Zag rotation

当操作节点同时具有父节点和祖先节点时,执行 zig-zag 旋转。但不同之处在于,祖先节点父节点和子节点采用 LRL 格式。该节点先向右旋转,然后向左旋转。

Zig Zag rotation

经过第一次旋转后,树如下:

left rotation

经过第二次旋转后的最终树如下:

root node 8

Zag-Zig rotation

当操作节点同时具有父节点和祖先节点时,也执行 zag-zig 旋转。但不同之处在于,祖先节点、父节点和子节点采用 RLR 格式。该节点先向左旋转,然后向右旋转。

Zag Zig rotation

进行了第一次旋转,得到如下树:

tree obtained

经过第二次旋转,最终得到如下树。然而,操作节点尚未成为根节点,因此需要执行另一次旋转,将该节点设为根。

after second rotation

Basic Operations of Splay Trees

伸展树包含二叉搜索树提供的所有基本操作:插入、删除和搜索。然而,在每个操作之后,都会有一个附加操作将其与二叉搜索树操作区分开来:伸展。我们已经学过伸展,因此,让我们理解其他操作的过程。

Insertion operation

伸展树中的插入操作与在二叉搜索树中执行插入操作的方式完全相同。在伸展树中执行插入操作的过程如下:

  1. 检查树是否为空;如果为空,则添加新节点并退出

insertion
  1. 如果树不为空,则使用二叉搜索插入将新节点添加到现有树中。

adding nodes
  1. 然后,选择并应用合适类型的伸展到新添加的节点。

splaying chosen

Zag (Left) Rotation is applied on the new node

left rotation applied

Example

以下是该操作在各种编程语言中的实现 −

Deletion operation

伸展树中的删除操作执行如下:

  1. 对要删除的节点应用伸展操作。

  2. 节点成为根后,删除该节点。

  3. 现在,树被分成两棵树,左子树和右子树;其各自的第一个节点为根节点:例如,root_left 和 root_right。

delete
  1. 如果 root_left 为 NULL 值,则 root_right 将成为树的根。反之亦然。

  2. 但如果 root_left 和 root_right 都不是 NULL 值,则从左子树中选择最大值并通过连接子树将其设为新根。

deleted 5 node

Example

以下是伸展树删除操作在各种编程语言中的实现:

Search operation

伸展树中的搜索操作遵循二叉搜索树操作的相同过程。然而,在进行搜索并找到元素之后,对搜索的节点应用伸展。如果找不到元素,则提示搜索不成功。

Example

以下是该操作在各种编程语言中的实现 −