数据结构算法-AVL树

数据结构算法-AVL树

1. AVL树介绍

AVL树(Adelson-Velsky and Landis Tree)是一种自平衡的二叉搜索树,其特点主要包括平衡性和高效的查找、插入和删除操作。‌‌

平衡性
AVL树通过维护每个节点的平衡因子(左子树高度与右子树高度之差)来保持树的平衡。平衡因子的值只能是-1、0或1。如果某个节点的平衡因子绝对值大于1,那么该树就失去了平衡,需要通过旋转操作来重新平衡。

高效的查找、插入和删除操作
由于AVL树保持了平衡,其查找、插入和删除操作的时间复杂度都能保持在O(log n)的范围内,其中n是树中节点的数量。这使得AVL树在处理大量数据时能够保持高效的性能。

旋转操作
当AVL树失去平衡时,会触发旋转操作来恢复平衡。旋转操作主要有四种:右旋(单旋)、左旋(单旋)、右-左双旋和左-右双旋。这些旋转操作通过改变树中节点的链接关系来降低树的高度,从而保持树的平衡。

应用场景
AVL树广泛应用于需要频繁插入、删除和查找操作的场景,如数据库索引、文件系统的目录结构、实时数据更新等。在这些场景中,AVL树能够保持高效的性能,确保数据处理的快速响应。

2. 源码

public class AvlTree {

    private AVLNode root = null;


    public void put(int key, Object value) {
        this.root = this.doPut(root, key, value);
    }
    
    public void delete(int key) {
        this.root = doDelete(root, key);
    }

    private AVLNode doDelete(AVLNode node, int key) {
        if (node == null) {
            return null;
        }
        if (key < node.key) {
            node.left = doDelete(node.left, key);
        } else if (key > node.key) {
            node.right = doDelete(node.right, key);
        } else {
            // 找到了
            // 只有一个孩子
            if (node.left == null) {
                node = node.right;
            } else if (node.right == null) {
                node = node.left;
            } else {
                // 有两个孩子
                // 找到后继节点
                AVLNode s = node.right;
                while (s.left != null) {
                    s = s.left;
                }
                // 删除后继节点, 因为会失衡, 返回删除后的根节点
                s.right = this.doDelete(node.right, s.key);
                s.left = node.left;
                node = s;
            }
        }
        if (node == null) {
            return null;
        }
        updateHeight(node);
        return balance(node);
        
    }

    private AVLNode doPut(AVLNode node, int key, Object value) {
        if (node == null) {
            return new AVLNode(key, value);
        }
        if (key == node.key) {
            node.value = value;
            return node;
        }
        if (key < node.key) {
            node.left = doPut(node.left, key, value);
        } else {
            node.right = doPut(node.right, key, value);
        }
        // 更新高度
        updateHeight(node);
        // 平衡二叉树
        return balance(node);
    }

    private AVLNode balance(AVLNode node) {
        if (node == null) {
            return null;
        }
        if (bf(node) > 1 && bf(node.left) >= 0) {
            //LL -> 右旋
            return rightRotation(node);
        } else if (bf(node) > 1 && bf(node.left) < 0) {
            // LR -> 左右旋
            node.left = leftRotation(node.left);
            return rightRotation(node);
        } else if (bf(node) < -1 && bf(node.right) < 0) {
            // RR -> 左旋
            return leftRotation(node);
        } else if (bf(node) < -1 && bf(node.right) >= 0) {
            // RL -> 右左旋
            node.right = rightRotation(node.right);
            return leftRotation(node);
        }
        return node;
    }

    private AVLNode rightRotation(AVLNode p) {
        AVLNode l = p.left;
        AVLNode lr = l.right;
        l.right = p;
        p.left = lr;
        updateHeight(p);
        updateHeight(l);
        return l;
    }
    
    private AVLNode leftRotation(AVLNode p) {
        AVLNode r = p.right;
        AVLNode rl = r.left;
        r.left = p;
        p.right = rl;
        updateHeight(p);
        updateHeight(r);
        return r;
    }

    private void updateHeight(AVLNode node) {
        node.height = Integer.max(height(node.left), height(node.right));
    }

    private int bf(AVLNode node) {
        return height(node.left) - height(node.right);
    }

    private int height(AVLNode node) {
        if (node == null) {
            return 0;
        }
        return node.height;
    }


    /**
     * 节点信息
     */
    static class AVLNode {

        int key;

        Object value;

        AVLNode left;

        AVLNode right;

        int height = 1;

        public AVLNode(int key, Object value) {
            this.key = key;
            this.value = value;
        }

    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值