数据结构-平衡二叉树(AVL树)(Java实现)

基于二叉排序树实现的AVL双旋转树
二叉平衡树 即 左右子树相差不会大于1
package datastructure.tree;

/*
    @CreateTime 2021/9/19 17:39
    @CreateBy cfk

*/

public class AvlTree {

    public static void main(String[] args) {
        int[] arr = {4,3,6,5,7,8};
        int[] arr1 = {10,11,7,6,8,9};
         /*
                  4
              3       6
                   5     7
                            8
         */

        AVLTreeSort avlTree = new AVLTreeSort();

        for (int i = 0; i < arr1.length; i++) {
            avlTree.add(new Node(arr1[i]));
        }

        avlTree.inOrder();

        System.out.println("在没有平衡处理树时的高度情况="+avlTree.getRoot().height());

        System.out.println("在没有平衡处理树时的左子树高度情况="+avlTree.getRoot().leftHeight());
        System.out.println("在没有平衡处理树时的右子树高度情况="+avlTree.getRoot().rightHeight());

        System.out.println("avl树的根节点是" + avlTree.getRoot());
        /*
                   6
               4      7
             3    5      8     4,3,6,5,7,8左旋转后生成的树  根节点为6
         */
    }
}

//创建二叉排序树
class AVLTreeSort{
    public Node root;

    public Node getRoot() {
        return root;
    }

    //添加节点
    public void add(Node node){
        if (root == null) {
            root = node;
        }else {
            root.add(node);
        }
    }

    //中序遍历
    public void inOrder() {
        if (root == null) {
            System.out.println("节点为空");
        }else {
            root.inOrder();
        }
    }

}


//创建节点
class Node {
    public int id;

    public Node left;
    public Node right;

    public Node(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                '}';
    }

    //==================================核心代码======================================
    //左旋转树
    //怎么处理进行左旋转
    public void leftRotate() {
        //1.创建一个新的节点newNode (以4这个值创建),创建一个新的节点,值等于当前根节点的值
        Node node = new Node(id);
        // 把新节点的左子树设置了当前节点的左子树  newNode.left = left
        node.left = left;
        // 2.把新节点的右子树设置为当前节点的右子树的左子树 newNode.right =right.left;
        node.right = right.left;
        // 3.把当前节点的值换为右子节点的值 value=right.value;
        id = right.id;
        // 4.把当前节点的右子树设置成右子树的右子树right=right.right;
        right=right.right;
        // 5.把当前节点的左子树设置为新节点 left=newLeft;
        left = node;
    }

    //右旋转 同左  只是左和右互换
    public void rightRotate(){
        Node node = new Node(id);
        node.right = right;
        node.left = left.right;
        id = left.id;
        left=left.left;
        right = node;
    }

    //获取二叉树的高度
    //需要两边节点的高度来判断进行左旋转还是右旋转
    public int height() {
        //这里取两边子树的最大值  默认根节点高度为1
        return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height())+1;
    }

    //获取二叉树的左子树高度
    public int leftHeight() {
        if (left == null) {
            return 0;
        }
        return left.height();
    }

    //获取二叉树的右子树高度
    public int rightHeight() {
        if (right == null) {
            return 0;
        }
        return right.height();
    }

    //==================================核心代码======================================


    //添加节点的方法
    public void add(Node node) {

        if (node == null) {
            return;
        }

        if (node.id < this.id) {
            //如果左节点为空
            if (left == null) {
                this.left = node;
            }else {
                //否则递归判断 把节点添加到左子节点的子节点 以此类推
                this.left.add(node);
            }

        }else {
            //如果右节点为空
            if (right == null) {
                this.right = node;
            }else {
                //同左节点
                this.right.add(node);
            }
        }
        //==================================核心代码======================================

        //如果左边子树高度-右边子树高度大于1 进行右旋转
        /*
            这里发现一个问题如果当左子树中右子树的高度大于右子树时 此时发生右旋转并没有生成一颗平衡二叉树
               10                                7
             7     11           =>           6      10
           6   8                                  8    11
                 9                                  9
                 所以我们进行的处理是先把左子树的右子树进行左旋转在对左子树进行右旋转
         */
        if ((leftHeight() - rightHeight()) > 1) {
            //如果节点不为空 并且左节点的右子树高度大于左子树的高度
            if (left != null && left.rightHeight() > left.leftHeight()) {
                left.leftRotate();
            }
            rightRotate();
            return;   //这里的退出一定要注意 如果不退出后面的程序不管如何也会进行
        }

        //如果右边子树高度-左边子树高度大于1 进行右旋转
        if ((rightHeight() - leftHeight()) > 1) {
            if (right != null && right.leftHeight() > right.rightHeight()) {
                right.rightRotate();
            }
            leftRotate();
        }

        //==================================核心代码======================================
    }

    //中序遍历
    public void inOrder() {
        if (this.left != null) {
            this.left.inOrder();
        }

        System.out.println("node=>"+this.id);

        if (this.right != null) {
            this.right.inOrder();
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值