Java数据结构与算法:平衡二叉树AVL、左旋转、右旋转、双向旋转、代码实现

文章目录

  • 平衡二叉树 AVL
      • . 向左旋转
      • . 向右旋转
      • . 双向旋转
      • . 代码实现


平衡二叉树 AVL

平衡二叉树是对二叉排序树的增强。
Java数据结构与算法:平衡二叉树AVL、左旋转、右旋转、双向旋转、代码实现_第1张图片

AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

性质:

  • 任何节点的两个子树的高度差最大差别为1
  • 增加和删除可能需要一次或多次树旋转来重新得到一个平衡树

. 向左旋转

当右子树的高度与左子树的高度差大于1时,就应该进行左旋转,降低右子树的高度,以达到平衡状态。

Java数据结构与算法:平衡二叉树AVL、左旋转、右旋转、双向旋转、代码实现_第2张图片

. 向右旋转

当左子树的高度与右子树的高度差大于1时,就应该进行右旋转,降低左子树的高度,以达到平衡状态。

Java数据结构与算法:平衡二叉树AVL、左旋转、右旋转、双向旋转、代码实现_第3张图片

. 双向旋转

Java数据结构与算法:平衡二叉树AVL、左旋转、右旋转、双向旋转、代码实现_第4张图片

如果不进行调整,直接向右旋转,得到的结果依旧不是AVL树

如果是向右旋转:

  • 那么就需要判断当前节点的左子节点的右子树的高度是否大于当前节点的左子节点的左子树,如果大于,就需要将左子节点的这个树,进行向左旋转的调整,调整完之后,再将当前节点向右旋转。

如果是向左旋转:

  • 那么就需要判断当前节点的右子节点的左子树的高度是否大于当前节点的右子节点的右子树,如果大于,就需要将左子节点的这个树,进行向右旋转的调整,调整完之后,再将当前节点向左旋转。

. 代码实现

public class AVLTreeDemo {
    public static void main(String[] args) {
        //int[] arr = {4,3,6,5,7,8}; // 左旋转测试
        //int[] arr = {10,12,8,9,7,6}; // 右旋转测试
        int[] arr = {10,11,7,6,8,9}; // 双旋转测试
        AvlTree avlTree = new AvlTree();
        for (int i = 0; i < arr.length; i++) {
            avlTree.add(new AvlNode(arr[i]));
        }
        avlTree.infixOrder();
        System.out.println("高:"+avlTree.getRoot().getTreeHeight());
        System.out.println("右:"+avlTree.getRoot().getRightTreeHeight());
        System.out.println("左:"+avlTree.getRoot().getLeftTreeHeight());
        System.out.println(avlTree.getRoot().value);
    }
}

class AvlTree{
    private AvlNode root;

    public AvlTree() {
    }

    public AvlTree(AvlNode root) {
        this.root = root;
    }

    public AvlNode getRoot() {
        return root;
    }

    public void add(AvlNode node){
        if (root==null){
            root=node;
        }else {
            root.add(node);
        }
    }

    public void infixOrder(){
        if (root==null){
            return;
        }else {
            root.infixOrder();
        }
    }

}

class AvlNode{
    int value;
    AvlNode left;
    AvlNode right;

    public AvlNode(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "AvlNode{" +
                "value=" + value +
                '}';
    }

    public void infixOrder(){
        if (this.left!=null){
            this.left.infixOrder();
        }
        System.out.println(this.toString());
        if (this.right!=null){
            this.right.infixOrder();
        }
    }

    // 二叉排序树添加节点操作
    public void add(AvlNode node){
        if (node==null){
            return;
        }
        if (node.value < this.value){
            if (this.left!=null){
                this.left.add(node);
            }else {
                this.left = node;
            }
        }else {
            if (this.right!=null){
                this.right.add(node);
            }else {
                this.right = node;
            }
        }

        // 在添加的过程中,就动态调整树的高度
        // 如果当前节点的右子树与左子树的高度差大于1,则向左旋转
        if (this.getRightTreeHeight()-this.getLeftTreeHeight() > 1){
            // 在向左旋转的时候,需要判断当前节点的右子树的左子树与右子树的高度差,
            // 如果当前节点的右子树的左子树高于当前节点的右子树的右子树,那么就需要将
            // 当前节点的右子树的子树向右旋转做一个平衡调整,再让当前节点向左旋转,才能保证平衡
            if (this.right.getLeftTreeHeight() > this.right.getRightTreeHeight()){
                this.right.rightRotate();
                this.leftRotate();
            }else {
                this.leftRotate(); // 向左旋转
            }
            return; // 一定要记得return,否则会出现严重错误
        }

        // 如果当前节点的左子树与右子树的高度差大于1,则向右旋转
        if (this.getLeftTreeHeight() - this.getRightTreeHeight() > 1){
            if (this.left.getRightTreeHeight() > this.left.getLeftTreeHeight()){
                this.left.leftRotate();
                this.rightRotate();
            }else {
                this.rightRotate(); // 向右旋转
            }
        }
    }

    // 获得高度
    public int getTreeHeight(){
        return Math.max(this.left==null ? 0 : this.left.getTreeHeight(), this.right==null ? 0 : this.right.getTreeHeight())+1;
    }

    // 获取当前节点的右子树的高度
    public int getRightTreeHeight(){
        if (this.right!=null){
            return this.right.getTreeHeight();
        }
        return 0;
    }

    // 获取当前节点的左子树的高度
    public int getLeftTreeHeight(){
        if (this.left!=null){
            return this.left.getTreeHeight();
        }
        return 0;
    }

    // 向左旋转
    public void leftRotate(){
        AvlNode newNode = new AvlNode(this.value);
        newNode.left = this.left;
        newNode.right = this.right.left;
        this.value = this.right.value;
        this.right = this.right.right;
        this.left = newNode;
    }

    // 向右旋转
    public void rightRotate(){
        AvlNode newNode = new AvlNode(this.value);
        newNode.right = this.right;
        newNode.left = this.left.right;
        this.value = this.left.value;
        this.left = this.left.left;
        this.right = newNode;
    }
}


本文截图来自:
https://www.bilibili.com/video/BV1E4411H73v?p=135

你可能感兴趣的:(Java数据结构与算法)