AVL树是一种自平衡二叉搜索树,其每个节点的左右子树高度差(平衡因子)绝对值不超过1。当插入或删除操作导致失衡时,通过旋转操作恢复平衡。
当平衡因子绝对值超过1时,需通过以下旋转调整:
失衡情况 | 旋转操作 | 应用场景 |
---|---|---|
右子树过高 | 左旋 | 插入到右子树的右子树(RR) |
左子树过高 | 右旋 | 插入到左子树的左子树(LL) |
左子树的右子树过高 | 左右旋 | 插入到左子树的右子树(LR) |
右子树的左子树过高 | 右左旋 | 插入到右子树的左子树(RL) |
场景:节点A的右子树高度比左子树高2,且右子节点B的右子树更高(RR失衡)。
A (平衡因子=-2)
\
B (平衡因子=-1)
\
C
步骤:
B (新根)
/ \
A C
\
T2
场景:节点A的左子树高度比右子树高2,且左子节点B的左子树更高(LL失衡)。
A (平衡因子=2)
/
B (平衡因子=1)
/
C
步骤:
B (新根)
/ \
C A
/
T2
场景:节点A的左子树B的右子树更高(LR失衡)。
A (平衡因子=2)
/
B (平衡因子=-1)
\
C
步骤:
Step 1: 左旋B
A
/
C
/
B
Step 2: 右旋A
C
/ \
B A
场景:节点A的右子树B的左子树更高(RL失衡)。
A (平衡因子=-2)
\
B (平衡因子=1)
/
C
步骤:
Step 1: 右旋B
A
\
C
\
B
Step 2: 左旋A
C
/ \
A B
class AVLNode:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
self.height = 1 # 节点高度
class AVLTree:
def insert(self, root, key):
# 1. 标准BST插入
if not root:
return AVLNode(key)
elif key < root.key:
root.left = self.insert(root.left, key)
else:
root.right = self.insert(root.right, key)
# 2. 更新节点高度
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
# 3. 计算平衡因子
balance = self.get_balance(root)
# 4. 根据失衡类型旋转
# 左左失衡 → 右旋
if balance > 1 and key < root.left.key:
return self.right_rotate(root)
# 右右失衡 → 左旋
if balance < -1 and key > root.right.key:
return self.left_rotate(root)
# 左右失衡 → 先左旋后右旋
if balance > 1 and key > root.left.key:
root.left = self.left_rotate(root.left)
return self.right_rotate(root)
# 右左失衡 → 先右旋后左旋
if balance < -1 and key < root.right.key:
root.right = self.right_rotate(root.right)
return self.left_rotate(root)
return root
def delete(self, root, key):
# 1. 标准BST删除
if not root:
return root
if key < root.key:
root.left = self.delete(root.left, key)
elif key > root.key:
root.right = self.delete(root.right, key)
else:
if root.left is None:
return root.right
elif root.right is None:
return root.left
# 找到右子树的最小节点替换
temp = self.get_min_node(root.right)
root.key = temp.key
root.right = self.delete(root.right, temp.key)
# 删除后若树为空直接返回
if root is None:
return root
# 2. 更新高度
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
# 3. 检查平衡
balance = self.get_balance(root)
# 左左失衡 → 右旋
if balance > 1 and self.get_balance(root.left) >= 0:
return self.right_rotate(root)
# 左右失衡 → 先左旋后右旋
if balance > 1 and self.get_balance(root.left) < 0:
root.left = self.left_rotate(root.left)
return self.right_rotate(root)
# 右右失衡 → 左旋
if balance < -1 and self.get_balance(root.right) <= 0:
return self.left_rotate(root)
# 右左失衡 → 先右旋后左旋
if balance < -1 and self.get_balance(root.right) > 0:
root.right = self.right_rotate(root.right)
return self.left_rotate(root)
return root
def left_rotate(self, z):
y = z.right
T2 = y.left
# 旋转
y.left = z
z.right = T2
# 更新高度
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
return y # 新根节点
def right_rotate(self, z):
y = z.left
T3 = y.right
# 旋转
y.right = z
z.left = T3
# 更新高度
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
return y # 新根节点
def get_height(self, root):
if not root:
return 0
return root.height
def get_balance(self, root):
if not root:
return 0
return self.get_height(root.left) - self.get_height(root.right)
def get_min_node(self, root):
current = root
while current.left:
current = current.left
return current
def pre_order(self, root):
if root:
print(f"{root.key} ", end="")
self.pre_order(root.left)
self.pre_order(root.right)
# 示例
avl = AVLTree()
root = None
keys = [10, 20, 30, 40, 50, 25]
for key in keys:
root = avl.insert(root, key)
print("前序遍历:", end=" ")
avl.pre_order(root) # 30 20 10 25 40 50
插入序列 [10, 20, 30, 40, 50, 25]
:
10 (失衡) 20
\ / \
20 → 10 30
\
30
20 30
/ \ / \
10 30 → 20 40
\
40
30 30 25
/ \ / \ / \
20 40 → 20 40 → 20 30
/ \ / \ / / \
10 25 10 25 10 25 40
红黑树是一种自平衡的二叉搜索树,通过在节点上增加一个颜色属性(红色或黑色)来维护树的平衡。它广泛应用于关联容器(如 C++ 的 std::map
和 Java 的 TreeMap
)中,因为它在插入、删除和查找操作中都能保持较好的性能。
红黑树满足以下性质:
这些性质确保了红黑树的关键特性:从根节点到叶子节点的最长路径不超过最短路径的两倍。
红黑树的核心操作包括插入、删除和查找。插入和删除操作可能会破坏红黑树的性质,因此需要通过旋转和重新着色来恢复平衡。
插入新节点时,默认将其颜色设置为红色,然后通过以下步骤调整树的结构:
插入示例:
插入 10 → 树为空,直接插入为根节点(黑色)。
插入 20 → 插入为 10 的右子节点(红色)。
插入 30 → 插入为 20 的右子节点(红色),触发旋转和重新着色。
删除节点时,可能会破坏红黑树的性质,因此需要通过以下步骤调整:
删除示例:
删除 20 → 用 10 替换 20,然后调整颜色和结构。
红黑树的查找操作与普通二叉搜索树相同,时间复杂度为 (O(\log n))。
红黑树通过旋转操作来调整树的结构,分为左旋和右旋。
场景:当节点的右子树过高时,执行左旋。
操作步骤:
图示:
A (失衡节点) B
\ / \
B → A C
\
C
场景:当节点的左子树过高时,执行右旋。
操作步骤:
图示:
A (失衡节点) B
/ / \
B → C A
/
C
class Node:
def __init__(self, value, color="red"):
self.value = value
self.color = color
self.left = None
self.right = None
self.parent = None
class RedBlackTree:
def __init__(self):
self.NIL = Node(None, "black") # 叶子节点
self.root = self.NIL
def insert(self, value):
new_node = Node(value)
new_node.left = self.NIL
new_node.right = self.NIL
self._insert_recursive(self.root, new_node)
self._fix_insert(new_node)
def _insert_recursive(self, root, new_node):
if root == self.NIL:
self.root = new_node
new_node.color = "black"
return
if new_node.value < root.value:
if root.left == self.NIL:
root.left = new_node
new_node.parent = root
else:
self._insert_recursive(root.left, new_node)
else:
if root.right == self.NIL:
root.right = new_node
new_node.parent = root
else:
self._insert_recursive(root.right, new_node)
def _fix_insert(self, node):
while node.parent.color == "red":
if node.parent == node.parent.parent.left:
uncle = node.parent.parent.right
if uncle.color == "red":
node.parent.color = "black"
uncle.color = "black"
node.parent.parent.color = "red"
node = node.parent.parent
else:
if node == node.parent.right:
node = node.parent
self._left_rotate(node)
node.parent.color = "black"
node.parent.parent.color = "red"
self._right_rotate(node.parent.parent)
else:
uncle = node.parent.parent.left
if uncle.color == "red":
node.parent.color = "black"
uncle.color = "black"
node.parent.parent.color = "red"
node = node.parent.parent
else:
if node == node.parent.left:
node = node.parent
self._right_rotate(node)
node.parent.color = "black"
node.parent.parent.color = "red"
self._left_rotate(node.parent.parent)
self.root.color = "black"
def _left_rotate(self, x):
y = x.right
x.right = y.left
if y.left != self.NIL:
y.left.parent = x
y.parent = x.parent
if x.parent == self.NIL:
self.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y
def _right_rotate(self, x):
y = x.left
x.left = y.right
if y.right != self.NIL:
y.right.parent = x
y.parent = x.parent
if x.parent == self.NIL:
self.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y
def inorder_traversal(self):
result = []
self._inorder(self.root, result)
return result
def _inorder(self, node, result):
if node != self.NIL:
self._inorder(node.left, result)
result.append((node.value, node.color))
self._inorder(node.right, result)
# 测试代码
rbt = RedBlackTree()
values = [10, 20, 30, 15, 25, 5]
for v in values:
rbt.insert(v)
print("中序遍历:", rbt.inorder_traversal())
特性 | 红黑树 | AVL 树 |
---|---|---|
平衡性 | 近似平衡 | 严格平衡 |
插入/删除性能 | 较快(旋转次数较少) | 较慢(旋转次数较多) |
查找性能 | 稍慢(树较高) | 较快(树较矮) |
应用场景 | 关联容器(如 std::map ) |
需要频繁查找的场景 |