返回

AVL 树:动态平衡二叉查找树

IOS

AVL树简介

AVL树是一种自平衡的二叉查找树,由 Georgy Adelson-Velsky 和 Evgenii Landis 在 1962 年提出。它与普通的二叉查找树不同,在添加、删除和查找操作时,AVL树会自动调整其结构,以确保树始终保持平衡。

AVL树的平衡性

AVL树的平衡性通过一个称为平衡因子(Balance Factor)的概念来衡量。平衡因子是树中每个节点的左子树和右子树的高度差。AVL树要求所有节点的平衡因子必须在 -1 到 1 之间。

AVL树的旋转

为了保持平衡,AVL树会在需要时进行旋转操作。旋转操作有两种类型:左旋和右旋。

  • 左旋 :当一个节点的平衡因子为 2 时,进行左旋操作。左旋操作将该节点的右子树的左子树提升为该节点的右子树,并将其右子树提升为该节点的根节点。

  • 右旋 :当一个节点的平衡因子为 -2 时,进行右旋操作。右旋操作将该节点的左子树的右子树提升为该节点的左子树,并将其左子树提升为该节点的根节点。

AVL树的优点

AVL树与二叉查找树相比,具有以下优点:

  • 更快的查找速度 :由于AVL树始终保持平衡,因此查找操作的时间复杂度始终为 O(log n)。
  • 更快的添加和删除速度 :由于AVL树在添加和删除节点时会自动调整结构,因此添加和删除操作的时间复杂度也始终为 O(log n)。
  • 更稳定的性能 :由于AVL树始终保持平衡,因此即使树中数据分布不均匀,其性能也不会受到太大影响。

AVL树的应用

AVL树广泛应用于各种需要快速查找、添加和删除数据的场景中,例如:

  • 数据库索引 :AVL树可以作为数据库索引的数据结构,以提高查询速度。
  • 缓存系统 :AVL树可以作为缓存系统的数据结构,以提高访问速度。
  • 文件系统 :AVL树可以作为文件系统的数据结构,以提高文件查找和管理的速度。

AVL树的实现

AVL树可以在多种编程语言中实现。以下是在 Python 中实现 AVL 树的代码示例:

class Node:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.left = None
        self.right = None
        self.height = 1


class AVLTree:
    def __init__(self):
        self.root = None

    def insert(self, key, value):
        new_node = Node(key, value)
        self.root = self._insert(self.root, new_node)

    def _insert(self, node, new_node):
        if node is None:
            return new_node

        if new_node.key < node.key:
            node.left = self._insert(node.left, new_node)
        else:
            node.right = self._insert(node.right, new_node)

        node.height = max(self._height(node.left), self._height(node.right)) + 1

        balance_factor = self._balance_factor(node)

        # Left Left Case
        if balance_factor > 1 and new_node.key < node.left.key:
            return self._right_rotate(node)

        # Right Right Case
        if balance_factor < -1 and new_node.key > node.right.key:
            return self._left_rotate(node)

        # Left Right Case
        if balance_factor > 1 and new_node.key > node.left.key:
            node.left = self._left_rotate(node.left)
            return self._right_rotate(node)

        # Right Left Case
        if balance_factor < -1 and new_node.key < node.right.key:
            node.right = self._right_rotate(node.right)
            return self._left_rotate(node)

        return node

    def _height(self, node):
        if node is None:
            return 0
        return node.height

    def _balance_factor(self, node):
        if node is None:
            return 0
        return self._height(node.left) - self._height(node.right)

    def _left_rotate(self, node):
        right_child = node.right
        node.right = right_child.left
        right_child.left = node

        node.height = max(self._height(node.left), self._height(node.right)) + 1
        right_child.height = max(self._height(right_child.left), self._height(right_child.right)) + 1

        return right_child

    def _right_rotate(self, node):
        left_child = node.left
        node.left = left_child.right
        left_child.right = node

        node.height = max(self._height(node.left), self._height(node.right)) + 1
        left_child.height = max(self._height(left_child.left), self._height(left_child.right)) + 1

        return left_child

    def search(self, key):
        return self._search(self.root, key)

    def _search(self, node, key):
        if node is None:
            return None

        if node.key == key:
            return node.value

        if key < node.key:
            return self._search(node.left, key)
        else:
            return self._search(node.right, key)

    def delete(self, key):
        self.root = self._delete(self.root, key)

    def _delete(self, node, key):
        if node is None:
            return node

        if key < node.key:
            node.left = self._delete(node.left, key)
        elif key > node.key:
            node.right = self._delete(node.right, key)
        else:
            if node.left is None:
                temp = node.right
                node = None
                return temp
            elif node.right is None:
                temp = node.left
                node = None
                return temp

            temp = self._get_predecessor(node.left)
            node.key = temp.key
            node.left = self._delete(node.left, temp.key)

        if node is None:
            return node

        node.height = max(self._height(node.left), self._height(node.right)) + 1

        balance_factor = self._balance_factor(node)

        # Left Left Case
        if balance_factor > 1 and self._balance_factor(node.left) >= 0:
            return self._right_rotate(node)

        # Left Right Case
        if balance_factor > 1 and self._balance_factor(node.left) < 0:
            node.left = self._left_rotate(node.left)
            return self._right_rotate(node)

        # Right Right Case
        if balance_factor < -1 and self._balance_factor(node.right) <= 0:
            return self._left_rotate(node)

        # Right Left Case
        if balance_factor < -1 and self._balance_factor(node.right) > 0:
            node.right = self._right_rotate(node.right)
            return self._left_rotate(node)

        return node

    def _get_predecessor(self, node):
        if node.right is None:
            return node

        return self._get_predecessor(node.right)

总结

AVL树是一种优异的二叉查找树,它能够在查找、添加和删除操作中提供稳定的对数时间复杂度。AVL树广泛应用于各种需要快速查找、添加和删除数据的场景中。