Javascript 中的 AVL 树旋转


为了保持平衡,AVL 树可能会执行以下四种旋转:

  • 左旋转
  • 右旋转
  • 左-右旋转
  • 右-左旋转

前两种旋转是单旋转,后两种旋转是双旋转。要使树不平衡,我们至少需要高度为 2 的树。通过这棵简单的树,让我们逐一了解它们。

左旋转

如果在右子树的右子树中插入节点时树变得不平衡,则我们执行单左旋转:

Left Rotation

在我们的示例中,节点 **A** 由于在 A 的右子树中插入了一个节点而变得不平衡。我们通过使 **A** 成为 **B** 的左子树来执行左旋转。这种旋转也称为 LL 旋转。让我们看看如何实现它:

function rotationLL(node) {
let tmp = node.left;
node.left = tmp.right;
tmp.right = node;
return tmp;
}

右旋转

如果在左子树的左子树中插入节点,AVL 树可能会变得不平衡。然后树需要右旋转。

Right Rotation

如图所示,通过执行右旋转,不平衡的节点成为其左子节点的右子节点。这也被称为 RR 旋转。让我们看看代码中它是如何实现的:

function rotationRR(node) {
let tmp = node.right;
node.right = tmp.left;
tmp.left = node;
return tmp;
}

左-右旋转

双旋转是已经解释过的旋转版本的稍微复杂一些的版本。为了更好地理解它们,我们应该注意旋转过程中执行的每个动作。让我们首先检查如何执行左-右旋转。左-右旋转是左旋转后跟着右旋转的组合。

状态动作
AVL Tree已将节点插入左子树的右子树中。这使得 **C** 成为不平衡节点。这些情况会导致 AVL 树执行左-右旋转。
Sub Tree我们首先对 **C** 的左子树执行左旋转。这使得 **A** 成为 **B** 的左子树。
Left Tree节点 **C** 仍然不平衡,但是现在,这是因为左子树的左子树。
Own Left Tree我们现在将对树进行右旋转,使 **B** 成为这个子树的新根节点。**C** 现在成为其自身左子树的右子树。
Tree Balanced树现在已平衡。

这也被称为 LR 旋转,因为我们首先执行左旋转,然后执行右旋转。可以使用之前的两种方法按如下方式实现:

function rotationLR(node) {
node.left = rotationRR(node.left);
return rotationLL(node);
}

右-左旋转

第二种类型的双旋转是右-左旋转。它是右旋转后跟着左旋转的组合。

状态动作
Balanced Tree已将节点插入右子树的左子树中。这使得 **A** 成为一个不平衡节点,平衡因子为 2。
Right Sub-Tree首先,我们在 **C** 节点沿进行右旋转,使 **C** 成为其自身左子树 **B** 的右子树。现在,**B** 成为 **A** 的右子树。
Unbalanced节点 **A** 仍然不平衡,因为其右子树的右子树需要左旋转。
Subtree通过使 **B** 成为子树的新根节点来执行左旋转。**A** 成为其右子树 **B** 的左子树。
Tree Balanced树现在已平衡。

这也被称为 RL 旋转,因为我们首先执行右旋转,然后执行左旋转。可以使用之前的两种方法按如下方式实现:

function rotationRL(node) {
node.right = rotationLL(node.right);
return rotationRR(node);
}

更新于:2020年6月15日

274 次浏览

启动你的 职业生涯

完成课程获得认证

开始学习
广告