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);
    }
相关推荐
Xiu Yan2 小时前
Java 转 C++ 系列:STL容器之list
java·开发语言·数据结构·c++·stl·list·visual studio
Mr_pyx2 小时前
【LeetCodeHOT100】 160. 相交链表 —— Java多解法详解
java·数据结构·链表
杨凯凡3 小时前
【016】集合框架总览:List/Set/Map 与线程安全
java·数据结构·list
自我意识的多元宇宙3 小时前
二叉树的遍历和线索二叉树--先序二叉树和后续二叉树
数据结构
im_AMBER3 小时前
Leetcode 159 无重复字符的最长子串 | 长度最小的子数组
javascript·数据结构·学习·算法·leetcode
郝学胜-神的一滴3 小时前
[力扣 105]二叉树前中后序遍历精讲:原理、实现与二叉树还原
数据结构·c++·算法·leetcode·职场和发展
LG.YDX3 小时前
笔试训练48天:mari和shiny(动态规划 - 线性dp)
数据结构·算法
承渊政道3 小时前
【递归、搜索与回溯算法】(floodfill算法:从不会做矩阵题,到真正掌握搜索扩散思想)
数据结构·c++·算法·leetcode·矩阵·dfs·bfs
_小草鱼_3 小时前
【数据结构】链表
数据结构·链表·数组·单链表·双链表