返回
程序员必备:C++ 实现 AVL 树,轻松搞定数据结构
后端
2023-08-25 01:43:29
AVL 树:自动平衡二叉搜索树指南
目录
- 什么是 AVL 树?
- AVL 树的性质
- AVL 树的实现
- C++ 代码示例
- 常见问题解答
什么是 AVL 树?
AVL 树是一种自平衡二叉搜索树,由 Adelson-Velskii 和 Landis 在 1962 年提出。它能够自动调整自身,以保持左右子树的高度差在 1 以内。这种性质使得 AVL 树非常适合用于数据结构和算法中,因为它可以保证查找、插入和删除操作的时间复杂度为 O(log n)。
AVL 树的性质
AVL 树具有以下性质:
- 它是一棵二叉搜索树。
- 对于每个节点,其左右子树的高度差至多为 1。
- 对于每个节点,其子树的高度是平衡的,即左子树的高度和右子树的高度相差不超过 1。
AVL 树的实现
AVL 树可以通过以下步骤来实现:
- 在插入或删除节点时,如果导致左右子树的高度差超过 1,则进行旋转操作,以恢复平衡。
- 旋转操作有四种类型:左旋、右旋、双左旋和双右旋。
- 旋转操作的时间复杂度为 O(1)。
C++ 代码示例
#include <iostream>
using namespace std;
class AVLNode {
public:
int data;
AVLNode *left;
AVLNode *right;
int height;
AVLNode(int data) {
this->data = data;
this->left = nullptr;
this->right = nullptr;
this->height = 1;
}
};
class AVLTree {
public:
AVLNode *root;
AVLTree() {
this->root = nullptr;
}
void insert(int data) {
this->root = insert(this->root, data);
}
AVLNode *insert(AVLNode *node, int data) {
if (node == nullptr) {
return new AVLNode(data);
}
if (data < node->data) {
node->left = insert(node->left, data);
} else if (data > node->data) {
node->right = insert(node->right, data);
} else {
return node;
}
updateHeight(node);
int balanceFactor = getBalanceFactor(node);
if (balanceFactor > 1) {
if (data < node->left->data) {
return rightRotate(node);
} else {
return leftRightRotate(node);
}
} else if (balanceFactor < -1) {
if (data > node->right->data) {
return leftRotate(node);
} else {
return rightLeftRotate(node);
}
}
return node;
}
void delete(int data) {
this->root = delete(this->root, data);
}
AVLNode *delete(AVLNode *node, int data) {
if (node == nullptr) {
return nullptr;
}
if (data < node->data) {
node->left = delete(node->left, data);
} else if (data > node->data) {
node->right = delete(node->right, data);
} else {
if (node->left == nullptr) {
AVLNode *temp = node->right;
delete node;
return temp;
} else if (node->right == nullptr) {
AVLNode *temp = node->left;
delete node;
return temp;
} else {
AVLNode *temp = findMin(node->right);
node->data = temp->data;
node->right = delete(node->right, temp->data);
}
}
updateHeight(node);
int balanceFactor = getBalanceFactor(node);
if (balanceFactor > 1) {
if (getBalanceFactor(node->left) >= 0) {
return rightRotate(node);
} else {
return leftRightRotate(node);
}
} else if (balanceFactor < -1) {
if (getBalanceFactor(node->right) <= 0) {
return leftRotate(node);
} else {
return rightLeftRotate(node);
}
}
return node;
}
bool search(int data) {
return search(this->root, data);
}
bool search(AVLNode *node, int data) {
if (node == nullptr) {
return false;
}
if (data < node->data) {
return search(node->left, data);
} else if (data > node->data) {
return search(node->right, data);
} else {
return true;
}
}
int findMin() {
return findMin(this->root);
}
int findMin(AVLNode *node) {
if (node->left == nullptr) {
return node->data;
} else {
return findMin(node->left);
}
}
int findMax() {
return findMax(this->root);
}
int findMax(AVLNode *node) {
if (node->right == nullptr) {
return node->data;
} else {
return findMax(node->right);
}
}
void updateHeight(AVLNode *node) {
node->height = max(getHeight(node->left), getHeight(node->right)) + 1;
}
int getHeight(AVLNode *node) {
if (node == nullptr) {
return 0;
} else {
return node->height;
}
}
int getBalanceFactor(AVLNode *node) {
if (node == nullptr) {
return 0;
} else {
return getHeight(node->left) - getHeight(node->right);
}
}
AVLNode *rightRotate(AVLNode *node) {
AVLNode *leftChild = node->left;
node->left = leftChild->right;
leftChild->right = node;
updateHeight(node);
updateHeight(leftChild);
return leftChild;
}
AVLNode *leftRotate(AVLNode *node) {
AVLNode *rightChild = node->right;
node->right = rightChild->left;
rightChild->left = node;
updateHeight(node);
updateHeight(rightChild);
return rightChild;
}
AVLNode *leftRightRotate(AVLNode *node) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
AVLNode *rightLeftRotate(AVLNode *node) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
void printPreOrder() {
printPreOrder(this->root);
}
void printPreOrder(AVLNode *node) {
if (node == nullptr) {
return;
}
cout << node->data << " ";
printPreOrder(node->left);
printPreOrder(node->right);
}
};
int main() {
AVLTree tree;
tree.insert(10);
tree.insert(20);
tree.insert(30);
tree.insert(40);
tree.insert(50);
tree.printPreOrder();
cout << endl;
tree.delete(20);
tree.printPreOrder();
cout << endl;
cout << tree.search(30) << endl;
cout << tree.findMin() << endl;
cout << tree.findMax() << endl;
return 0;
}
常见问题解答
1. AVL 树与其他平衡二叉搜索树有什么区别?
AVL 树与红黑树和替罪羊树等其他平衡二叉搜索树类似,但它们在旋转操作和平衡要求方面有所不同。AVL 树要求左右子树的高度差至多为 1,而红黑树和替罪羊树允许更大的高度差。
2. AVL 树的插入和删除操作的时间复杂度是多少?
AVL 树的插入和删除操作的时间复杂度为 O(log n),其中 n 是树中的节点数。这是因为平衡操作在 O(1) 时间内执行。
3. AVL 树在哪些应用中特别有用?
AVL