AVL树的插入操作(四种情况)


前言

主要内容为AVL树的插入操作(不包含重复值),主要分为四种情况:

  • 右旋(Single Right Rotation)
  • 左旋(Single Left Rotation)
  • 先左旋后右旋(Left-Right Rotation)
  • 先右旋后左旋(Left-Right Rotation)

一、AVL树简介

AVL树本质上是一颗平衡二叉树,但是它又具有以下特点:

  • 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1
  • 左右两个子树都是一棵平衡二叉树

AVL树可视化网站:https://www.cs.usfca.edu/~galles/visualization/AVLtree.html

平衡因子bf

AVL树的每个节点都有一个平衡因子(Balance Factor)

节点n的平衡因子表示为:n的左子树的高度 - n的右子树的高度
在这里插入图片描述
一棵AVL树的平衡因子的取值只能是:-1、0、1,否则AVL树不平衡,需要恢复平衡。不平衡的时候平衡因子只能为-2或者2.
在这里插入图片描述

二、AVL树的插入操作(不包含重复值)

1.找到要插入的位置(和普通的二叉搜索树一样)

递归插入:

  • 如果要插入的数据比当前节点大,则插入到右子树
  • 如果要插入的数据比当前节点小,则插入到左子树
AVLTree<T> newAVL = new AVLTree<>(value, leftNode, rightNode);
        // Ensure input is not null.
        if (value == null)
            throw new IllegalArgumentException("Input cannot be null");

        if (element.compareTo(value) > 0) {
            newAVL.rightNode = rightNode.insert(element);
        } else if (element.compareTo(value) < 0) {
            newAVL.leftNode = leftNode.insert(element);
        } else {
            return this;
        }

2.平衡化

插入数据后,可能会使得AVL树不平衡,主要分为下列四种情况:

  • 插入位置为不平衡点的左节点的左子树(此时不平衡点的bf=2,其左节点的bf=1)
  • 插入位置为不平衡点的右节点的右子树(此时不平衡点的bf=-2,其右节点的bf=-1)
  • 插入位置为不平衡点的左节点的右子树(此时不平衡点的bf=2,其左节点的bf=-1)
  • 插入位置为不平衡点的右节点的左子树(此时不平衡点的bf=-2,其右节点的bf=1)

在这里插入图片描述

情况1:右旋(Single Right Rotation)

插入位置(A)为不平衡点的左节点的左子树(此时不平衡点的bf=2,其左节点的bf=1)
在这里插入图片描述

情况2:左旋(Single Left Rotation)

插入位置(N)为不平衡点的右节点的右子树(此时不平衡点的bf=-2,其右孩子的bf=-1)
在这里插入图片描述

情况3:先左旋后右旋(Left-Right Rotation)

插入位置(B1)为不平衡点的左节点的右子树(此时不平衡点的bf=2,其左节点的bf=-1)

左旋:
在这里插入图片描述
右旋:
在这里插入图片描述

情况4:先右旋后左旋(Left-Right Rotation)

插入位置为不平衡点的右节点的左子树(此时不平衡点的bf=-2,其右节点的bf=1)

和先左旋后右旋过程对称,故省略。

相关代码

public AVLTree<T> insert(T element) {
        AVLTree<T> newAVL = new AVLTree<>(value, leftNode, rightNode);
        // Ensure input is not null.
        if (value == null)
            throw new IllegalArgumentException("Input cannot be null");
        if (element.compareTo(value) > 0) {
            newAVL.rightNode = rightNode.insert(element);
        } else if (element.compareTo(value) < 0) {
            newAVL.leftNode = leftNode.insert(element);
        } else {
            return this;
        }

        //4 cases for imbalance
        int balanceFactor = newAVL.getBalanceFactor();
        if(balanceFactor == 2){
            if (((AVLTree<T>) newAVL.leftNode).getBalanceFactor() < 0) {
                newAVL.leftNode = ((AVLTree<T>) newAVL.leftNode).leftRotate();
            }
            return newAVL.rightRotate();
        }
        else if(balanceFactor == -2){
            if (((AVLTree<T>) newAVL.rightNode).getBalanceFactor() > 0) {
                newAVL.rightNode = ((AVLTree<T>) newAVL.rightNode).rightRotate();
            }
            return newAVL.leftRotate();
        }
        return newAVL; 
    }

    /**
     * Conducts a left rotation on the current node.
     *
     * @return the new 'current' or 'top' node after rotation.
     */
    public AVLTree<T> leftRotate() {  
        Tree<T> newParent = this.rightNode;
        Tree<T> newRightOfCurrent = newParent.leftNode;
        this.rightNode = newRightOfCurrent;
        newParent.leftNode = this;
        return (AVLTree<T>) newParent; 
    }

    /**
     * Conducts a right rotation on the current node.
     *
     * @return the new 'current' or 'top' node after rotation.
     */
    public AVLTree<T> rightRotate() {
        Tree<T> newParent = this.leftNode;
        Tree<T> newLeftOfCurrent = newParent.rightNode;
        this.leftNode = newLeftOfCurrent;
        newParent.rightNode = this;
        return (AVLTree<T>) newParent;  // Change to return something different
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值