侧边栏壁纸
博主头像
拾荒的小海螺博主等级

只有想不到的,没有做不到的

  • 累计撰写 225 篇文章
  • 累计创建 19 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

JAVA:实现平衡二叉树(AVL Tree)及其应用实践

拾荒的小海螺
2025-07-08 / 0 评论 / 1 点赞 / 3 阅读 / 5903 字

🌲 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)

d2e9015e7be848ef88c1b9fdd3a8d6f9.jpeg


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 做数据缓存自动清理功能,也可以继续告诉我,我可以为你写一个完整项目模板 😎

1

评论区