平衡二叉树和AVL

平衡二叉树和AVL树是在二分搜索树的基础上进行讲解
回忆二分搜索树的问题:
添加数据 :是按照顺序添加的 32145
每个节点的左节点小于根节点,每个节点的右节点都大于根节点
在这里插入图片描述

一、AVL

AVL树得名于它的发明者G.M.Adelson-Velsky 和 E.M.Landis
AVL树最早发明的自平衡二分搜索树

二、平衡二叉树

平衡二叉树的要求:对于任意一个节点,左子树和右子树的高度差不能超过1
(1)一颗满二叉树和完全二叉树是平衡二叉树

在这里插入图片描述
(2)线段树也是平衡二叉树

在这里插入图片描述
(3)如果按照以前的二分搜索树的方式,分别添加节点 2 和 7 ,此棵树就不是平衡二叉树。
为了能保持这课二叉树的平衡,就要标注每个节点的高度
在这里插入图片描述
计算出平衡因子(左右子树的高度差) 最终高度差不能相差1
在这里插入图片描述

三、代码实现

(1)获取节点高度

    //获取节点高度
    private int getheight(Node node) {
   
        if (node == null) {
   
            return 0;
        }
        return node.heigth;
    }

(2)获取节点的平衡因子

    //获取平衡因子
    private int getBalance(Node node) {
   
        if (node == null) {
   
            return 0;
        }
        return getheight(node.left) - getheight(node.right);
    }

(3)判断是不是二分搜索树


    //判断是否是二分搜索树
    public boolean isBST() {
   
        return isBST(root);
    }

(4)根据中序遍历的结果进行判断是不是二分搜索树


    //中序遍历的结果进行判断   左 中 右
    private boolean isBST(Node node) {
   
        List<T> list = new ArrayList<>();
        inorderTraversal(node, list);
        for (int i = 0; i < list.size() - 1; i++) {
   
            if (list.get(i).compareTo(list.get(i + 1)) > 0) {
   
                return false;
            }
        }
        return true;
    }

(5)中序遍历

    //中序遍历
    private void inorderTraversal(Node node, List<T> list) {
   
        if (node == null) {
   
            return;
        }
        inorderTraversal(node.left, list);
        list.add(node.val);
        inorderTraversal(node.right, list);
    }

(6)判断是否是平衡二叉树

  //判断是否是平衡二叉树
    public boolean isBalanceTree() {
   
        return isBalanceTree(root);
    }

    private boolean isBalanceTree(Node node) {
   
        //如果根节点为空,也为平衡树
        if (node == null) {
   
            return true;
        }
        //根节点不为空情况如下   平衡因子的绝对值
        int balance = Math.abs(getBalance(node));
        if (balance > 1) {
   
            return false;
        }
        return isBalanceTree(node.left) && isBalanceTree(node.right);
    }

四、测试

  AVLtree<Integer> AVLtree =new AVLtree();
        int[] arr = {
   23,12,11,5,6,8,25};
        for (int i = 0; i <arr.length; i++) {
   
          AVLtree.add(arr[i]);
        }
        System.out.println(AVLtree.isBST());
        System.out.println(AVLtree.isBalanceTree());
        System.out.println(AVLtree);

在这里插入图片描述

五、AVL的左旋转和右旋转

(1)维护平衡的时机

加入节点后,沿着节点向上维护平衡性

(2)插入的元素在不平衡节点的左侧的左侧

依次插入 12 8 5
在这里插入图片描述
右旋维持平衡
在这里插入图片描述
第一步:
在这里插入图片描述
第二步:
在这里插入图片描述

右旋代码实现

    //AVL树的右旋   根节点为x
    public Node rightrotate(Node x) {
   
        Node y = x.left;    //将根节点的左节点赋值为 y节点
        Node t2 = y.right;   //将y节点的右侧赋值为t2  断开右侧节点
        y.right = x;		//右旋转,将根节点赋值给y的右侧
        x.left = t2;		//将断开的t2 ,连接到x根节点的左侧
        //更新height
        x.heigth = Math.max(getheight(x.left), getheight(x.right)) + 1;
        y.heigth = Math.max(getheight(y.left), getheight(y.right)) + 1;
        return y;
    }

(3)插入的元素在不平衡节点的右侧的右侧

依次插入 5 8 12
在这里插入图片描述
左旋维持平衡
在这里插入图片描述
第一步:
在这里插入图片描述
第二步:
在这里插入图片描述

左旋代码实现


    //AVL树的左旋
    public Node leftrotate(Node x) {
   
        Node y = x.right;   //根节点为x ,将根节点的右侧赋值为y节点
        Node t2 = y.left;   //将y节点的左侧断开 ,并赋值为t2
        y.left = x;			//将节点x赋值在y节点的左侧
        x.right = t2;		//将断开的t2 ,连接到x节点的右侧
        //更新height
        x.heigth = Math.max(getheight(x.left), getheight(x.right)) + 1;
        y.heigth = Math.max(getheight(y.left)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值