二叉平衡树-java语言描述

二叉平衡树

1、概念

​ 是一颗空树或者左右两个子树的高度差不超过 1,且左右子树本身也都是一颗平衡二叉树

2、将一棵普通的二叉树变为一棵平衡二叉树
/*
当一棵树的右子树的高度减去左子树的高度大于 1的时候
使用左旋转来将二叉树变为平衡二叉树
步骤:
1、创建一个新的节点 newNode,这个新节点的值等于当前根节点的值
2、把新节点的左子节点指向根节点的左子节点
3、把新节点的右子节点指向为根节点的右子节点的左子节点
4、把根节点的值替换为根节点的右子节点的值
5、把根节点的右子节点指向根节点的右子节点的右子节点
6、把根节点的左子节点指向下新节点

当一棵树的左子树的高度减去右子树的高度大于 1的时候
使用右旋转来将二叉树变为平衡二叉树
步骤:
1、创建一个新的节点 newNode,这个新节点的值等于当前根节点的值
2、把新节点的右子节点指向根节点的右子节点
3、把新节点的左子节点指向为根节点的左子节点的右子节点
4、把根节点的值替换为根节点的左子节点的值
5、把根节点的左子节点指向根节点的左子节点的左子节点
6、把根节点的右子节点指向下新节点

注意:
1、当符合右旋转,但是它的左子节点的右子树高度大于它的左子节点的左子树高度时
1.1、先对根节点的左节点进行左旋转
1.2、在对根节点进行右旋转即可
2、当符合左旋转,但是它的右子节点的左子树高度大于它的右子节点的右子树高度时
2.1、先对根节点的右节点进行右旋转
2.2、在对根节点进行左旋转即可
*/
//左旋转
//返回以该节点为根节点的高度
    public int height() {
        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 void leftRotate() {
        Nodes newNodes = new Nodes(this.getValue());
        newNodes.setLeft(this.getLeft());
        newNodes.setRight(this.getRight().getLeft());
        this.setValue(this.getRight().getValue());
        this.setRight(this.getRight().getRight());
        this.setLeft(newNodes);
    }
//右旋转
//返回以该节点为根节点的高度
    public int height() {
        return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
    }

//返回右子树的高度
    public int rightHeight() {
        if (right == null) {
            return 0;
        }
        return right.height();
    }

//右旋转二叉树
    public void rightRotate() {
        Nodes newNodes = new Nodes(this.getValue());
        newNodes.setRight(this.getRight());
        newNodes.setLeft(this.getLeft().getRight());
        this.setValue(this.getLeft().getValue());
        this.setLeft(this.getLeft().getLeft());
        this.setRight(newNodes);
    }
	/**
     * 添加节点
     *
     * @param node 需要添加的值
     */
    public void add(Nodes node) {
        if (node == null) {
            return;
        }
        //判断传入的节点与当前节点的关系来决定如何插入
        if (node.getValue() < this.value) {
            //如果当前节点的左节点为空
            if (this.getLeft() == null) {
                this.setLeft(node);
            } else {
                this.getLeft().add(node);
            }
        } else {
            //如果当前节点的右节点为空
            if (this.getRight() == null) {
                this.setRight(node);
            } else {
                this.getRight().add(node);
            }
        }

        //当添加完一个元素之后,判断右子树高度减去左子树高度是否大于1,如果大于,则左旋转
        if (this.rightHeight() - this.leftHeight() > 1) {
            //如果它的左子树的右子树高度大于它的左子树的左子树高度
            if (this.getRight() != null && this.getRight().leftHeight() > this.getRight().rightHeight()) {
                //先对当前节点进行左旋转
                this.getRight().rightRotate();
                //在对当前节点进行右旋转
                leftRotate();
            } else {
                leftRotate();
            }
            return;
        }
        //当添加完一个元素之后,判断左子树高度减去右子树高度是否大于1,如果大于,则右旋转
        if (this.leftHeight() - this.rightHeight() > 1) {
            //如果它的左子树的右子树高度大于它的左子树的左子树高度
            if (this.getLeft() != null && this.getLeft().rightHeight() > this.getLeft().leftHeight()) {
                //先对当前节点进行左旋转
                this.getLeft().leftRotate();
                //在对当前节点进行右旋转
                rightRotate();
            } else {
                rightRotate();
            }
        }
    }
3、完整的代码
public class AVLTreeDemo {
    public static void main(String[] args) {
        int[] array = {10, 11, 7, 6, 8, 9};
        AVLTree avlTree = new AVLTree();
        for (int i = 0; i < array.length; i++) {
            avlTree.add(new Nodes(array[i]));
        }
        //遍历
        System.out.print("中序遍历:");
        avlTree.middleOrder();
        System.out.println();

        System.out.println("树的高度:" + avlTree.getRoot().height());
        System.out.println("树的左子树的高度:" + avlTree.getRoot().leftHeight());
        System.out.println("树的右子树的高度:" + avlTree.getRoot().rightHeight());
    }
}

//AVL树
class AVLTree {
    private Nodes root;

    public Nodes getRoot() {
        return root;
    }

    //添加节点的办法
    public void add(Nodes nodes) {
        if (root == null) {
            root = nodes;
        } else {
            root.add(nodes);
        }
    }

    //中序遍历
    public void middleOrder() {
        if (root != null) {
            root.middleOrder();
        } else {
            System.out.println("二叉排序树为空,不能遍历!");
        }
    }

}

//节点类
class Nodes {
    private int value;
    private Nodes left;
    private Nodes right;

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

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Nodes getLeft() {
        return left;
    }

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

    public Nodes getRight() {
        return right;
    }

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

    //返回左子树的高度
    public int leftHeight() {
        if (left == null) {
            return 0;
        }
        return left.height();
    }

    //返回右子树的高度
    public int rightHeight() {
        if (right == null) {
            return 0;
        }
        return right.height();
    }

    //返回以该节点为根节点的高度
    public int height() {
        return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
    }

    //左旋转二叉树
    public void leftRotate() {
        Nodes newNodes = new Nodes(this.getValue());
        newNodes.setLeft(this.getLeft());
        newNodes.setRight(this.getRight().getLeft());
        this.setValue(this.getRight().getValue());
        this.setRight(this.getRight().getRight());
        this.setLeft(newNodes);
    }

    //右旋转二叉树
    public void rightRotate() {
        Nodes newNodes = new Nodes(this.getValue());
        newNodes.setRight(this.getRight());
        newNodes.setLeft(this.getLeft().getRight());
        this.setValue(this.getLeft().getValue());
        this.setLeft(this.getLeft().getLeft());
        this.setRight(newNodes);
    }

    /**
     * 添加节点
     *
     * @param node 需要添加的值
     */
    public void add(Nodes node) {
        if (node == null) {
            return;
        }
        //判断传入的节点与当前节点的关系来决定如何插入
        if (node.getValue() < this.value) {
            //如果当前节点的左节点为空
            if (this.getLeft() == null) {
                this.setLeft(node);
            } else {
                this.getLeft().add(node);
            }
        } else {
            //如果当前节点的右节点为空
            if (this.getRight() == null) {
                this.setRight(node);
            } else {
                this.getRight().add(node);
            }
        }

        //当添加完一个元素之后,判断右子树高度减去左子树高度是否大于1,如果大于,则左旋转
        if (this.rightHeight() - this.leftHeight() > 1) {
            //如果它的左子树的右子树高度大于它的左子树的左子树高度
            if (this.getRight() != null && this.getRight().leftHeight() > this.getRight().rightHeight()) {
                //先对当前节点进行左旋转
                this.getRight().rightRotate();
                //在对当前节点进行右旋转
                leftRotate();
            } else {
                leftRotate();
            }
            return;
        }
        //当添加完一个元素之后,判断左子树高度减去右子树高度是否大于1,如果大于,则右旋转
        if (this.leftHeight() - this.rightHeight() > 1) {
            //如果它的左子树的右子树高度大于它的左子树的左子树高度
            if (this.getLeft() != null && this.getLeft().rightHeight() > this.getLeft().leftHeight()) {
                //先对当前节点进行左旋转
                this.getLeft().leftRotate();
                //在对当前节点进行右旋转
                rightRotate();
            } else {
                rightRotate();
            }
        }
    }

    //中序遍历
    public void middleOrder() {
        if (this.left != null) {
            this.left.middleOrder();
        }
        System.out.print(this.getValue() + "->");
        if (this.right != null) {
            this.right.middleOrder();
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值