JAVA实现 - AVL树

二叉搜索树的哪些节点需要旋转 ?

如果一个节点的左右孩子,高度差超过1,则此节点失衡,才需要旋转

AVL树:

  • 二叉搜索树在插入和删除时,节点可能失衡
  • 如果在插入和删除时通过旋转,始终让二叉搜索树保持平衡,称为自自平衡的二叉搜索树
  • AVL是自平衡二叉搜索树的实现之一

高度和平衡因子

平衡因子(balance factor) = 左子树的高度 - 右子树的高度

  • bf = -1 ,bf = 0,bf = 1 为平衡节点,
  • bf>1: 表示左边太高
  • bf<-1: 表示右边太高
package com.datastructure.binarytree.avltree;

public class AVLTree {


    static class AVLNode{
        int key;
        Object value;
        AVLNode left;
        AVLNode right;
        int height = 1;

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

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

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

    /**
     * 获取AVL树节点的高度
     * @param node
     * @return
     */
    public int height(AVLNode node){
        return node == null ? 0:node.height;
    }

    /**
     * 更新节点的高度(新增、删除、旋转)
     * @param node
     */
    public void updateHeight(AVLNode node){
        node.height = Integer.max(height(node.left), height(node.right)) + 1;
    }

    /**
     * 求节点的平衡因子(balance factor) = 左子树的高度 - 右子树的高度
     *  性质: -1,0,1 为平衡节点,
     *  bf>1: 表示左边太高
     *  bf<-1: 表示右边太高
     * @param node
     * @return
     */
    public int bf(AVLNode node){
        return height(node.left) - height(node.right);
    }
}

失衡的四种情况

颜色意义:
黄色:上移
红色:下移
绿色:换爹

LL:

  • 失衡节点的bf > 1,即左边更高
  • 失衡节点的左孩子的bf>=0,即左孩子这边也是左边更高或等高

LR:

  • 失衡节点的bf > 1,即左边更高
  • 失衡节点的左孩子的bf<0,即左孩子这边是右边更高

RL:

  • 失衡节点的bf<-1,即右边更高
  • 失衡节点的右孩子的bf>0,即右孩子这边左边更高

RR:

  • 失衡节点的bf<-1,即右边更高
  • 失衡节点的右孩子的bf<=0,即右孩子这边右边更高或等高

旋转

  • 红色和黄色节点旋转后高度可能回发生变化,因此旋转后需要更新高度信息,其他节点旋转后高度不变
  • 更新高的顺序不能发生变化,必须先更新位置较低的红色节点的高度,再更新位置较高的黄色节点的高度
package com.datastructure.binarytree.avltree;

public class AVLTree {

    ...
  
    //右旋
    public AVLNode rightRotate(AVLNode red){
        AVLNode yellow = red.left;
        AVLNode green = yellow.right;
        //上位
        yellow.right = red;
        //绿色换爹
        red.left = green;
        updateHeight(red);  //更新高度
        updateHeight(yellow); //更新高度
        return yellow;
    }

    //左旋
    public AVLNode leftRotate(AVLNode red){
        AVLNode yellow = red.right;
        AVLNode green = yellow.left;
        //上位
        yellow.left = red;
        //绿色换爹
        red.right = green;

        updateHeight(red);  //更新高度
        updateHeight(yellow); //更新高度
        return yellow;
    }

    //先左子树左旋,再根节点右旋
    public AVLNode leftRightNode(AVLNode node){
        node.left = leftRotate(node.left); //左子树左旋
        return rightRotate(node);
    }

    //先右子树右旋,再根节点左旋
    public AVLNode rightLeftNode(AVLNode node){
         node.right = rightRotate(node.right);
        return leftRightNode(node);
    }
}

平衡

package com.datastructure.binarytree.avltree;

public class AVLTree {

    ...
    
    public AVLNode balance(AVLNode node){
        if(node == null){
            return null;
        }

        int bf = bf(node);
        /*
        等于0,比较特殊发生再删除时.6节点失衡,6的高度差为0
                6
               /
              3
             / \
            1   5
         */
        if (bf > 1 && bf(node.left) >= 0){ //左边失衡,LL
            return rightRotate(node);
        }else if(bf > 1 && bf(node.left) <0 ) { //LR
            return leftRightNode(node);
        }else if(bf < -1 && bf(node.right) >0 ){ //右边失衡,RL
            return rightLeftNode(node);
        }else if (bf < -1 && bf(node.right) <= 0){ // RR
            return leftRightNode(node);
        }
        return node;
    }

}

更新节点

package com.datastructure.binarytree.avltree;

public class AVLTree {


    ...

    AVLNode root;

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

    public AVLNode doPut(AVLNode curr, int key, Object value) {

        //1.找到空位,返回节点
        if (curr == null) {
            return new AVLNode(key, value);
        }
        //2.找到更新
        if (key == curr.key) {
            //找到
            curr.value = value;
            return curr;
        }
        //3.没找到继续找
        if (key < curr.key) {
            curr.left = doPut(curr.left, key, value);
        } else {
            curr.right = doPut(curr.right, key, value);
        }
        //4.更新节点攻读
        updateHeight(curr);
        //5.平衡节点
        return balance(curr);
    }
}

删除节点

package com.datastructure.binarytree.avltree;

public class AVLTree {
    
    ...

    /**
     * 根据key删除节点
     *
     * @param key
     * @return
     */
    public AVLNode remove(int key) {
        root = doRemove(root, key);
        return null;
    }

    /**
     * 递归删除方法
     *
     * @param curr 被删除的树
     * @param key  需要删除的key
     * @return 删剩下的节点
     */
    public AVLNode doRemove(AVLNode curr, int key) {
        if (curr == null) {
            return null;
        }
        //1.没找到key
        if (key < curr.key) {
            curr.left = doRemove(curr.left, key);
        } else if (curr.key < key) {
            curr.right = doRemove(curr.right, key);
        } else {
            //2.找打key:1)key为叶子节点 2)只有左孩子 3) 只有右孩子
            if (curr.left == null && curr.right == null) { //叶子节点
                return null;
            } else if (curr.left == null) { // 只有右孩子
                curr = curr.right;
            } else if (curr.right == null) { //只有左孩子
                curr = curr.left;
            } else {  //既有左孩子也有右孩子,寻找后继节点
                AVLNode s = curr.right; //后继节点
                while(s.left != null){
                    s = s.left;
                }
                //找到后继节点
                s.right = doRemove(curr.right,s.key);
                s.left = curr.left;
            }
        }
        //更新高度
        updateHeight(curr);
        //检查平衡
        return balance(curr);
    }
}
posted @   chuangzhou  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2022-01-01 UnitTest 框架学习
点击右上角即可分享
微信分享提示