🌲 1、简述
在高并发系统中,我们经常需要在保证有序性、可查询性以及插入/删除效率的前提下,对大量数据进行管理。这时,平衡二叉树(AVL Tree) 就是一个优秀的选择。
什么是平衡二叉树?
平衡二叉树(AVL Tree)是 带有平衡条件的二叉查找树,它保证 任意节点的左右子树高度差不超过1,从而维持整体的平衡性。
与普通的 BST(Binary Search Tree)相比,AVL 树具有更稳定的时间复杂度:
操作 | 平均时间复杂度 | 最坏时间复杂度 |
---|---|---|
查找 | O(log n) | O(log n) |
插入 | O(log n) | O(log n) |
删除 | O(log n) | O(log n) |
2、AVL 树原理核心
当插入或删除节点导致某节点的平衡因子(左右子树高度差)变为 -2
或 +2
时,就需要进行旋转来维持平衡。旋转操作包括:
- 右旋(LL)
- 左旋(RR)
- 先左后右旋(LR)
- 先右后左旋(RL)
实践应用场景
- 🔍 缓存数据排序管理(按访问时间、优先级排序)
- 🧾 数据去重且有序插入(如日志系统)
- 🛍️ 电商商品推荐系统中的实时热度排序
- 🧠 人工智能中的启发式搜索(如 A)*
- 💼 数据库索引实现(如某些自研KV存储)
3、实践样例
这里是一个简单的 AVL 树实现,用于支持插入和中序遍历。
🔧 AVL 节点定义
class AVLNode {
int key, height;
AVLNode left, right;
AVLNode(int key) {
this.key = key;
this.height = 1;
}
}
🌲 AVL 树核心操作
public class AVLTree {
private AVLNode root;
// 获取高度
private int height(AVLNode node) {
return node == null ? 0 : node.height;
}
// 获取平衡因子
private int getBalance(AVLNode node) {
return node == null ? 0 : height(node.left) - height(node.right);
}
// 右旋
private AVLNode rightRotate(AVLNode y) {
AVLNode x = y.left;
AVLNode T2 = x.right;
x.right = y;
y.left = T2;
y.height = Math.max(height(y.left), height(y.right)) + 1;
x.height = Math.max(height(x.left), height(x.right)) + 1;
return x;
}
// 左旋
private AVLNode leftRotate(AVLNode x) {
AVLNode y = x.right;
AVLNode T2 = y.left;
y.left = x;
x.right = T2;
x.height = Math.max(height(x.left), height(x.right)) + 1;
y.height = Math.max(height(y.left), height(y.right)) + 1;
return y;
}
// 插入节点
public AVLNode insert(AVLNode node, int key) {
if (node == null) 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 return node; // 不允许重复
node.height = 1 + Math.max(height(node.left), height(node.right));
int balance = getBalance(node);
// 平衡调整
if (balance > 1 && key < node.left.key) return rightRotate(node); // LL
if (balance < -1 && key > node.right.key) return leftRotate(node); // RR
if (balance > 1 && key > node.left.key) { // LR
node.left = leftRotate(node.left);
return rightRotate(node);
}
if (balance < -1 && key < node.right.key) { // RL
node.right = rightRotate(node.right);
return leftRotate(node);
}
return node;
}
public void add(int key) {
root = insert(root, key);
}
// 中序遍历
public void inorder(AVLNode node) {
if (node != null) {
inorder(node.left);
System.out.print(node.key + " ");
inorder(node.right);
}
}
public void printTree() {
inorder(root);
System.out.println();
}
}
🧪 测试代码
public class Main {
public static void main(String[] args) {
AVLTree avl = new AVLTree();
int[] data = {10, 20, 30, 40, 50, 25};
for (int num : data) {
avl.add(num);
}
avl.printTree(); // 输出:10 20 25 30 40 50(已平衡)
}
}
4、总结
特性 | 说明 |
---|---|
平衡性好 | 插入删除均可保持 O(log n) |
自动旋转 | 无需手动维护结构 |
支持排序 | 中序遍历天然有序 |
缺点 | 实现复杂,频繁插入/删除性能略低于 B 树 |
📌 实战建议:
- 若偏向范围查询和排序,AVL 非常合适;
- 若插入频繁并且并发高,可以考虑跳表、红黑树或基于链表的结构;
- 可用于构建 Java TreeMap 的底层模型、消息中间件的优先任务调度队列等。
如果你想实现 AVL 树的删除、范围查询、或结合 SpringBoot 做数据缓存自动清理功能,也可以继续告诉我,我可以为你写一个完整项目模板 😎
评论区