返回
AVL树:平衡二叉搜索树的秘密武器
前端
2023-10-15 04:48:00
AVL树:一种自平衡的二叉搜索树
AVL树简介
AVL树,得名于它的发明者Adelson-Velsky和Landis,是一种自平衡二叉搜索树。与普通二叉搜索树不同,AVL树通过保持左右子树的高度平衡来优化搜索、插入和删除操作,从而确保它们的时间复杂度为O(log n)。
AVL树结构
每个AVL树节点包含三个值:
- 键: 用于标识节点的值
- 左子树: 节点所有左子节点的集合
- 右子树: 节点所有右子节点的集合
AVL树平衡性
AVL树通过左右子树高度平衡来保证其效率。如果左右子树高度差超过1,树将进行旋转操作以恢复平衡。
AVL树旋转
旋转操作有四种类型,用于平衡AVL树:
- 左左旋转: 当左子树高度大于右子树高度时
- 右右旋转: 当右子树高度大于左子树高度时
- 左右旋转: 当左子树高度大于右子树高度,且左子节点右子树高度大于左子树高度时
- 右左旋转: 当右子树高度大于左子树高度,且右子节点左子树高度大于右子树高度时
AVL树插入
插入操作遵循以下步骤:
- 将新节点插入树中
- 从新节点向上回溯,检查左右子树高度差是否超过1
- 如果高度差超过1,执行旋转操作来平衡树
代码示例(C++)
class AVLNode {
public:
int key;
AVLNode *left;
AVLNode *right;
int height;
AVLNode(int key) {
this->key = key;
left = right = nullptr;
height = 1;
}
};
class AVLTree {
public:
AVLNode *root;
AVLTree() {
root = nullptr;
}
void insert(int key) {
root = insert(root, key);
}
private:
AVLNode *insert(AVLNode *node, int key) {
if (node == nullptr) {
return new AVLNode(key);
}
if (key < node->key) {
node->left = insert(node->left, key);
} else if (key > node->key) {
node->right = insert(node->right, key);
} else {
// Key already exists in the tree
}
updateHeight(node);
return balance(node);
}
AVLNode *balance(AVLNode *node) {
int balanceFactor = getBalanceFactor(node);
if (balanceFactor > 1) {
if (getBalanceFactor(node->left) < 0) {
node->left = leftRotate(node->left);
}
return rightRotate(node);
} else if (balanceFactor < -1) {
if (getBalanceFactor(node->right) > 0) {
node->right = rightRotate(node->right);
}
return leftRotate(node);
}
return node;
}
AVLNode *leftRotate(AVLNode *node) {
AVLNode *newRoot = node->right;
node->right = newRoot->left;
newRoot->left = node;
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
AVLNode *rightRotate(AVLNode *node) {
AVLNode *newRoot = node->left;
node->left = newRoot->right;
newRoot->right = node;
updateHeight(node);
updateHeight(newRoot);
return newRoot;
}
void updateHeight(AVLNode *node) {
node->height = max(getHeight(node->left), getHeight(node->right)) + 1;
}
int getHeight(AVLNode *node) {
if (node == nullptr) {
return 0;
}
return node->height;
}
int getBalanceFactor(AVLNode *node) {
if (node == nullptr) {
return 0;
}
return getHeight(node->left) - getHeight(node->right);
}
};
AVL树删除
删除操作遵循以下步骤:
- 找到要删除的节点
- 从树中删除节点
- 从被删除节点的父节点向上回溯,检查左右子树高度差是否超过1
- 如果高度差超过1,执行旋转操作来平衡树
AVL树复杂度
AVL树的搜索、插入和删除操作的时间复杂度均为O(log n)。
AVL树应用
AVL树广泛应用于:
- 数据库
- 文件系统
- 内存管理
常见问题解答
1. AVL树和普通二叉搜索树有什么区别?
AVL树通过平衡左右子树高度来优化搜索、插入和删除操作,从而保证O(log n)的时间复杂度,而普通二叉搜索树没有这种平衡性。
2. AVL树是如何保持平衡的?
通过旋转操作,当左右子树高度差超过1时,AVL树会执行旋转操作以恢复平衡。
3. AVL树的插入和删除操作是如何工作的?
插入操作将新节点插入树中,然后检查平衡性并执行旋转操作;删除操作将节点从树中删除,然后检查平衡性并执行旋转操作。
4. AVL树的优点是什么?
- O(log n)的时间复杂度
- 易于插入、删除和搜索
5. AVL树的局限性是什么?
- 维护平衡的开销
- 比普通二叉搜索树更复杂