Java高阶数据结构|AVL树

AVL树

对于二叉搜索树而言,当存在单分支有序结构时,查找效率会非常差,此时AVL树可以有效解决这个问题

AVL树的插入

  1. 按照二叉搜索树的方式插入新节点
java 复制代码
        TreeNode node=new TreeNode(val);
        if (root==null){
            root=node;
            return true;
        }
        TreeNode cur=root;
        TreeNode parent=null;
        while (cur!=null) {
            if (cur.val < val) {
                parent = cur;
                cur = cur.right;
            } else if (cur.val == val) {
                return false;
            } else {
                parent = cur;
                cur = cur.left;
            }
        }
            if (parent.val<val){
                parent.right=node;
            }else{
                parent.left=node;
            }
            node.parent=parent;
            cur=node;
  1. 调整节点的平衡因子
java 复制代码
            //平衡因子的修改

            while(parent!=null){

                //先看cur是parent的左还是右  决定平衡因子是++还是--

                if(cur==parent.right){

                    //如果是右树,那么右树高度增加 平衡因子++

                    parent.bf++;
                }else {

                    //如果是左树,那么左树高度增加 平衡因子--

                    parent.bf--;
                }

AVL树的旋转

java 复制代码
    //检查当前的平衡因子 是不是绝对值 1  0  -1

                if (parent.bf==0){

                    //说明已经平衡了

                    break;
                } else if (parent.bf == 1 || parent.bf == -1) {

                    //继续向上去修改平衡因子

                    cur=parent;
                    parent=cur.parent;
                }else {
                    if (parent.bf==2){

                        //右树高-》需要降低右树的高度

                        if (cur.bf==1){

                            //左旋

                            rotateLeft(parent);
                        }else {

                            //cur.bf==-1(右左)

                            rotateRL(parent);
                        }
                    }else {

                        //parent.bf == -2 左树高-》需要降低左树的高度

                        if (cur.bf==-1){

                            //右旋

                            rotateRight(parent);
                        }else {

                            //cur.bf==1(左右)

                            rotateLR(parent);
                        }
                    }

                    //上述代码走完就平衡了

                    break;
                }
            }
  1. 新节点插入较高左子树的左侧---右单旋
java 复制代码
  private void rotateRight(TreeNode parent) {
        TreeNode subL=parent.left;
        TreeNode subLR=subL.right;
        parent.left=subLR;
        subL.right=parent;

        //没有subLR

        if(subLR!=null){
            subLR.parent=parent;
        }

        //必须先记录

        TreeNode Pparent=parent.parent;
        parent.parent=subL;

        //检查 当前是不是就是根节点

        if (root==parent){
            root=subL;
            root.parent=null;
        }else {

            //不是根节点,判断这棵子树是左子树还是右子树

            if (parent==Pparent.left){
                Pparent.left=subL;
            }else {
                Pparent.right=subL;
            }
            subL.parent=Pparent;
        }
        subL.bf=0;
        parent.bf=0;
    }

2.新节点插入较高右子树的右侧---左单旋

'

java 复制代码
private void rotateLeft(TreeNode parent) {
        TreeNode subR=parent.right;
        TreeNode subRL=subR.left;
        parent.right=subRL;
        subR.left=parent;
        if (subRL!=null){
            subRL.parent=parent;
        }
        TreeNode Pparent=parent.parent;
        if (root==parent){
            root=subR;
            root.parent=null;
        }else{
            if (parent==Pparent.left){
                Pparent.left=subR;
            }else {
                Pparent.right=subR;
            }
            subR.parent=Pparent;
        }
        subR.bf=0;
        parent.bf=0;
    }

3.新节点插入较高左子树的右侧:先左单旋再右单旋--左右双旋

java 复制代码
private void rotateLR(TreeNode parent) {
        TreeNode subL=parent.left;
        TreeNode subLR=subL.right;
        int bf=subLR.bf;
        rotateLeft(parent.left);
        rotateRight(parent);
        if (bf==-1){
            subL.bf=0;
            subLR.bf=0;
            parent.bf=1;
        }else if(bf==1){
            subL.bf=-1;
            subLR.bf =0;
            parent.bf=0;
        }
    }
  1. 新节点插入较高右子树的左侧---右左:先右单旋再左单旋--右左双旋
java 复制代码
 private void rotateRL(TreeNode parent) {
        TreeNode subR=parent.right;
        TreeNode subRL=subR.left;
        int bf= subRL.bf;
        rotateRight(parent.right);
        rotateLeft(parent);
        if (bf==-1){
            parent.bf=0;
            subRL.bf=0;
            subR.bf=1;
        }else if(bf==1) {// bf=0的情况在在上面的左旋与右旋已经调整完了
            parent.bf=-1;
            subRL.bf=0;
            subR.bf=0;
        }
    }

AVL树的验证

  1. 验证其为二叉搜索树

如果中序遍历可得到一个有序的序列,就说明为二叉搜索树

java 复制代码
//中序遍历的结果是有序的 就能说明当前树 一定是AVL树吗?  不一定的

    public void inorder(TreeNode root){
        if (root==null){
            return;
        }
        inorder(root.left);
        System.out.println(root.val+" ");
        inorder(root.right);
    }
  1. 验证其为平衡树

每个节点子树高度差的绝对值不超过1(注意节点中如果没有平衡因子)

节点的平衡因子是否计算正确

java 复制代码
 public int height(TreeNode root){
        if (root==null){
            return 0;
        }
        int leftH=height(root.left);
        int rightH=height(root.right);
        return leftH > rightH ? leftH+1 : rightH+1;
    }
    public boolean isBalanced(TreeNode root){
        if(root==null)  return true;
        int leftH=height(root.left);
        int rightH=height(root.right);
        if (rightH-leftH!=root.bf){
            System.out.println("这个节点:"+root.val+"平衡因子异常");
            return false;
        }
        return Math.abs(leftH-rightH)<=1
                &&isBalanced(root.left)
                &&isBalanced(root.right);
    }
相关推荐
Darling噜啦啦5 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠6 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾6 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres8216 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q6 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒6 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记6 天前
单项不带头不循环链表
数据结构·链表
小糯米6016 天前
JS 数组
数据结构·算法·排序算法
小欣加油6 天前
leetcode3612 用特殊操作处理字符串I
数据结构·c++·算法·leetcode·职场和发展
凌波粒6 天前
LeetCode--90.子集II(回溯算法)
数据结构·算法·leetcode