📜  AVL树|套装2(删除)(1)

📅  最后修改于: 2023-12-03 15:29:32.477000             🧑  作者: Mango

AVL树 | 套装2(删除)

简介

AVL树是一种自平衡二叉搜索树,它的平衡性是通过旋转操作来实现的。它的时间复杂度与树的高度有关,所以平衡性是至关重要的。

本篇文章将介绍如何实现AVL树的删除操作。

删除操作实现

AVL树的删除分为以下几步:

  1. 执行二叉搜索树的删除操作,将待删除节点删除。
  2. 自下而上地递归更新所有祖先节点的平衡因子。
  3. 从待删除节点的父节点开始,往上遍历第一个平衡因子绝对值大于1的节点,对该节点进行旋转操作。
  4. 重复步骤3直到根节点。
删除节点
def delete_node(self, key: Any) -> None:
    if self.root is None:
        return

    node = self._search(self.root, key)

    if node is None:
        return

    parent = node.parent

    if node.left_child is None:
        self._transplant(node, node.right_child, parent)
    elif node.right_child is None:
        self._transplant(node, node.left_child, parent)
    else:
        successor = self._minimum(node.right_child)
        if successor.parent != node:
            self._transplant(successor, successor.right_child, successor.parent)
            successor.right_child = node.right_child
            successor.right_child.parent = successor
        self._transplant(node, successor, parent)
        successor.left_child = node.left_child
        successor.left_child.parent = successor

    self._update_height_all(parent)

    if parent is None:
        return

    while parent is not None:
        if abs(self._balance_factor(parent)) > 1:
            if self._balance_factor(parent) > 1 and self._balance_factor(parent.left_child) >= 0:
                self._right_rotate(parent)
            elif self._balance_factor(parent) > 1 and self._balance_factor(parent.left_child) < 0:
                self._left_rotate(parent.left_child)
                self._right_rotate(parent)
            elif self._balance_factor(parent) < -1 and self._balance_factor(parent.right_child) <= 0:
                self._left_rotate(parent)
            elif self._balance_factor(parent) < -1 and self._balance_factor(parent.right_child) > 0:
                self._right_rotate(parent.right_child)
                self._left_rotate(parent)
        
        parent = parent.parent

我们首先执行二叉搜索树的删除操作,将待删除节点删除。然后从待删除节点的父节点开始,往上遍历所有祖先节点,逐一更新它们的平衡因子。最后,我们从待删除节点的父节点开始,往上遍历第一个平衡因子绝对值大于1的节点,对该节点进行旋转操作,直到根节点。

旋转操作

旋转操作是AVL树实现自平衡的核心。我们可以分别实现左旋和右旋操作。当一个节点的平衡因子绝对值大于1时,我们需要通过旋转操作将其变平衡。

下面是左旋和右旋的代码实现:

def _left_rotate(self, node: AVLNode) -> None:
    r = node.right_child
    node.right_child = r.left_child

    if r.left_child is not None:
        r.left_child.parent = node

    r.parent = node.parent

    if node.parent is None:
        self.root = r
    elif node == node.parent.left_child:
        node.parent.left_child = r
    else:
        node.parent.right_child = r

    r.left_child = node
    node.parent = r

    self._update_height(node)
    self._update_height(r)

def _right_rotate(self, node: AVLNode) -> None:
    l = node.left_child
    node.left_child = l.right_child

    if l.right_child is not None:
        l.right_child.parent = node

    l.parent = node.parent

    if node.parent is None:
        self.root = l
    elif node == node.parent.right_child:
        node.parent.right_child = l
    else:
        node.parent.left_child = l

    l.right_child = node
    node.parent = l

    self._update_height(node)
    self._update_height(l)
更新平衡因子

为了更新祖先节点的平衡因子,我们可以从待删除节点的父节点开始,往上遍历所有祖先节点,逐一更新它们的平衡因子。

def _update_height_all(self, node: AVLNode) -> None:
    if node is None:
        return

    self._update_height(node)

    self._update_height_all(node.parent)
结语

这篇文章介绍了如何实现AVL树的删除操作。通过递归更新祖先节点的平衡因子和旋转操作,我们可以保证AVL树的平衡性。