积树成林 --- 平衡二叉树到底平不平衡,他说了算!树旋转

在上篇博客中已经提到平衡二叉树
平衡二叉树左子树和右子树 的高度差的绝对值不超过1的二叉排序树

定义节点:

public class AVLTreeNode {
    private int value;//结点的数据
    private int height;//树的高度
    private AVLTreeNode left;//指向左孩子结点
    private AVLTreeNode right;//指向左孩子结点
    public AVLTreeNode(int value) {
        this.value = value;
        this.height = 0;
        this.left = null;
        this.right =null;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }
    public AVLTreeNode getLeft() {
        return left;
    }
    public void setLeft(AVLTreeNode left) {
        this.left = left;
    }
    public AVLTreeNode getRight() {
        return right;
    }
    public void setRight(AVLTreeNode right) {
        this.right = right;
    }
}

为平衡而生的旋转

1.LL旋转

左左单旋转时, 不满足AVL条件的最小树的根应该下移,该树的其他节点上移,而不管该树的左子树的右孩子或者存在或者不存在,在旋转过程中,都要把该左子树的的右孩子添加以作为最小树根的左孩子,因为即使不存在,添加null 也不影响最后的旋转效果

在这里插入图片描述

    /**
     * @Author ZHfei 
     * @Description //TODO LL左旋转,顺时针
     * @Date 18:59 2020/6/7
     **/
    public AVLTreeNode singleRotateLeft(AVLTreeNode x){
        AVLTreeNode w=  x.getLeft();
        x.setLeft(w.getRight());
        w.setRight(x);
        x.setHeight(Math.max(Height(x.getLeft()),Height(x.getRight()))+1);
        w.setHeight(Math.max(Height(w.getLeft()),x.getHeight())+1);
        return w;
    }
/**
     * @Author ZHfei 
     * @Description //TODO 求树的高度
     * @Date 18:58 2020/6/7
     **/
    //求树的高度
    public int Height(AVLTreeNode root) {
        if (root == null) {
            return -1;
        }else {
            return root.getHeight();
        }
    }

2.RR旋转

右右单旋转时, 不满足AVL条件的最小树的根应该下移,该树的其他节点上移,而不管该树的右子树的左孩子或者存在或不存在,在旋转过程中,都要把该右子树的左孩子添加以作为最小树根的右孩子,因为即使不存在,添加null 也不影响最后的 旋转效果

在这里插入图片描述

    /**
     * @Author ZHfei
     * @Description //TODO RR右旋转,逆时针
     * @Date 18:59 2020/6/7
     **/

    public AVLTreeNode singleRotateRight(AVLTreeNode w){
        AVLTreeNode x=  w.getRight();
        w.setRight(x.getLeft());
        x.setLeft(w);
        w.setHeight(Math.max(Height(w.getRight()),Height(w.getLeft()))+1);
        x.setHeight(Math.max(Height(x.getRight()),w.getHeight())+1);
        return x;
    }

3.LR旋转
在这里插入图片描述

  /**
     * @Author ZHfei
     * @Description //TODO LR旋转
     * @Date 19:00 2020/6/7
     **/
    public AVLTreeNode doubleRotateLeft(AVLTreeNode z){
        z.setLeft(singleRotateRight(z.getLeft()));//在X和Y之间旋转
        return singleRotateLeft(z);//在Z和Y之间旋转
    }

4.RL旋转
在这里插入图片描述

   /**
     * @Author ZHfei
     * @Description //TODO RL旋转
     * @Date 19:01 2020/6/7
     **/

    public AVLTreeNode doubleRotateRight(AVLTreeNode x){
        x.setRight(singleRotateRight(x.getLeft()));//在Z和Y之间旋转
        return singleRotateRight(x);//在X和Y之间旋转
    }

如何判断进行单旋转还是双旋转 (什么时候需要单旋转,而什么时候需要多旋转?)

1。高度不平衡需要α点的两棵子树高度差为2,故可得高度不平衡可能出现在下面四种情况中:

① 对α的左儿子的左子树进行一次插入。

② 对α的左儿子的右子树进行一次插入。

③ 对α的右儿子的左子树进行一次插入。

④ 对α的右儿子的右子树进行一次插入。

1.单旋转: 插入点不介于 不满足AVL条件的树根 和 树根对应孩子节点之间; (情形①、③ 即 左-左、右-右)

2.双旋转:插入点介于 不满足AVL条件的树根 和 树根对应孩子节点之间;(情形②、④ 即 左-右、右-左)

AVL的插入:

 /**
     * @Author ZHfei
     * @Description //TODO 插入操作
     * @Date 19:01 2020/6/7
     **/
    public AVLTreeNode insert(AVLTreeNode root, int data) {
        if (root == null) {
            root = new AVLTreeNode(data);//若原树为空, 生成并返回一个结点的AVL树
        }else if (data < root.getValue()) {
            root.setLeft(insert(root.getLeft(),data));
            if (Height(root.getLeft())-Height(root.getRight()) == 2) {
                if (data < root.getLeft().getValue()) {
                    root = singleRotateLeft(root);
                }else {
                    root = doubleRotateLeft(root);
                }
            }
        } else if (data > root.getValue()) {
            root.setRight(insert(root.getRight(),data));
            if (Height(root.getRight())-Height(root.getLeft()) == 2) {
                if (data < root.getRight().getValue()) {
                    root = singleRotateRight(root);
                } else {
                    root = doubleRotateRight(root);
                }
            }
        }
        /*否则,数据已经存在,程序什么也不做。*/
        root.setHeight(Math.max(Height(root.getLeft()),Height(root.getRight()))+1);
        return root;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值