返回
AVL 树:动态平衡二叉查找树
IOS
2023-11-03 08:24:38
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树广泛应用于各种需要快速查找、添加和删除数据的场景中。