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);
    }
相关推荐
星子yu5 分钟前
【Java数据结构】二叉树 好像就这样?
java·数据结构
Beyond_System|系统之外16 分钟前
【学编程】Python基础编程题100道(1-20)
java·数据结构·算法
船厂电气自动化ai大模型28 分钟前
AI大模型与数学 第75课 基、维度、向量空间坐标
数据结构·线性代数·算法·机器学习·推荐算法
程序员阿鹏12 小时前
为什么MySQL InnoDB选择B+树?
数据结构·数据库·b树·sql·mysql·算法·缓存
郝学胜-神的一滴14 小时前
C++11 工程级应用 09:告别无谓拷贝,解锁高性能移动语义
开发语言·数据结构·c++·vscode·软件工程·visual studio
2601_9657422214 小时前
全媒体运营与短视频代运营,两者有什么区别?
大数据·数据结构·人工智能·算法·ai·媒体
彧azz15 小时前
数据结构:关于图的学习
c语言·数据结构·笔记·学习·算法
彧azz16 小时前
二叉搜索树学习记录
c语言·数据结构·笔记·算法
suhan17 小时前
【数据结构】二、线性表:2.单链表的定义与实现(带头结点与不带头结点的区别)
数据结构
AgentMaster20 小时前
数据治理工具选型指南:一套可复用的四阶段决策框架
大数据·数据结构·人工智能·算法