AVL树详解

相关文章链接:

相关文章链接 第2节 数据结构

观前提示:

本文所使用的Eclipse版本为Photon Release (4.8.0),IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141,Tomcat版本为9.0.12。

1. 简介

AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。

特点

  1. 本身首先是一棵二叉搜索树。

  2. 带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。

平衡因子: 某结点的左子树与右子树的高度(深度)差即为该结点的平衡因子(BF,Balance Factor)。平衡二叉树上所有结点的平衡因子只可能是 -1,0 或 1。

2. 插入

这里只介绍插入节点后破坏平衡所做的旋转操作。

2.1 单向右旋平衡处理LL

在左子树(L)的左孩子(L)插入节点失衡,需要进行单向右旋平衡处理LL。

在这里插入图片描述

在这里插入图片描述

2.2 单向左旋平衡处理RR

在右子树(R)的右孩子(R)插入节点失衡,需要进行单向左旋平衡处理RR。
在这里插入图片描述
在这里插入图片描述

2.3 双向旋转(先左后右)平衡处理LR

在左子树(L)的右孩子(R)插入节点失衡,需要进行双向旋转(先左后右)平衡处理LR。

在这里插入图片描述
在这里插入图片描述

2.4 双向旋转(先右后左)平衡处理RL

在右子树(R)的左孩子(L)插入节点失衡,需要进行双向旋转(先右后左)平衡处理RL。
在这里插入图片描述

在这里插入图片描述

3. 删除

AVL树删除操作步骤如下

  1. 搜索给定的key,确定其是否在树中。

  2. 如果不在树中,返回null;如果在树中,执行标准的BST删除操作,并返回该删除的结点。

  3. 检查被删除结点的所有祖先结点是否平衡,如果不平衡,则执行重平衡操作。

BST删除操作三种情况

  1. 当该节点为叶子节点,则让该节点的父节点指向其变为NULL,然后释放节点。

  2. 当该节点不是叶子节点,但左子树或者右子树为空,则:
    (1)若左子树为空,则让该节点父节点指向其右节点。
    (2)若右子树为空,则让该节点父节点指向其左节点。

  3. 当该节点不是叶子节点,且左子树和右子树都不为空,则:
    (1)在该节点的左子树中找到最大节点Lmax(该节点必然是一个叶子节点)或者右子树中的最小节点Rmin,取出节点的值value,并删除该节点。
    (2)将value的值赋到要删除的节点。

4 java代码例子

AVL树 AVLTree.java

package TestTree.AVL;

public class AVLTree {
   

    private Integer root;
    private AVLTree left;
    private AVLTree right;
    private Integer height;

    public AVLTree(Integer root) {
   
        this.root = root;
    }

    public Integer getRoot() {
   
        return root;
    }

    public void setRoot(Integer root) {
   
        this.root = root;
    }

    public AVLTree getLeft() {
   
        return left;
    }

    public void setLeft(AVLTree left) {
   
        this.left = left;
    }

    public AVLTree getRight() {
   
        return right;
    }

    public void setRight(AVLTree right) {
   
        this.right = right;
    }

    public Integer getHeight() {
   
        return height;
    }

    /**
     * 获取指定节点深度
     * @param node
     * @return
     */
    public static Integer getHeight(AVLTree node){
   
        if(node == null){
   
            return 0;
        }
        return node.height;
    }

    public void setHeight(Integer height) {
   
        this.height = height;
    }

    /**
     * 指定节点深度赋值
     * @param node
     * @param height
     */
    public static void setHeight(AVLTree node, Integer height) {
   
        if(node == null){
   
            return;
        }
        node.height = height;
    }

    /**
     * 获取最小节点
     * @param node
     * @return
     */
    public static AVLTree getMinNode(AVLTree node){
   
        if(node != null && node.getLeft() == null){
   
            return node;
        }
        return getMinNode(node.getLeft());
    }
}

树操作工具类 TreeOperateUtil.java

package TestTree.AVL;

/**
 * 树操作工具类
 * @author jjy
 * @date 2020-10-19
 */
public class TreeOperateUtil {
   

    /**
     * 插入节点
     * @param node
     * @param data
     * @return
     */
    public static AVLTree insert(AVLTree node, int data){
   
        // 根节点没有数据,直接插入
        if(node == null || node.getRoot() == null){
   
            node = new AVLTree(data);
            node.setHeight(1);
            return node;
        }

        if(node.getRoot() > data){
   
            node.setLeft(insert(node.getLeft(), data));
        } else {
   
            node.setRight(insert(node.getRight(), data));
        }

        // 更新深度
        node.setHeight(1 + Math.max(AVLTree.getHeight(node.getLeft()), AVLTree.getHeight(node.getRight())));
        int balanceFactor = getBalanceFactor(node);

        // LL
        if(balanceFactor == 2 && getBalanceFactor(node.getLeft()) > 0 ){
   
            System.out.println("-------------LL旋转-------------");
            return LLRotate(node);
        }

        // LR
        if(balanceFactor == 2 && getBalanceFactor(node.getLeft()) < 0){
   
            System.out.println("-------------LR旋转-------------");
            return LRRotate(node);
        }

        // RR
        if(balanceFactor == -2 && getBalanceFactor(node.getRight()) < 0){
   
            System.out.println("-------------RR旋转-------------");
            return RRRotate(node);
        }

        // RL
        if(balanceFactor == -2 && getBalanceFactor(node.getRight()) > 0){
   
            System.out.println("-------------RL旋转-------------");
            return RLRotate(node);
        }

        return node;
    }

    /**
     * 删除节点
     * @param node
     * @param data
     * @return
     */
    public static AVLTree remove(AVLTree node, int data){
   
        if(node == null){
   
            return null;
        }
        if(node.getRoot() > data){
   
            node.setLeft(remove(node.getLeft(), data));
        } else if( node.getRoot() < data){
   
            node.setRight(remove(node.getRight(), data));
        } else {
   

            if(node.getLeft() == null) {
   
                // 没有左子树
                node = node.getRight();
            } else if(node.getRight() == null) {
   
                // 没有右子树
                node = node.getLeft();
            } else {
   
                // 左右子树均不为空,取右子树最小值(或者左子树最大值),替换当前要删除的节点
                AVLTree minNode = AVLTree.getMinNode(node.getRight());
                node.setRight(remove(node.getRight(), minNode.getRoot
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值