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);
    }
相关推荐
夏日听雨眠1 小时前
数据结构(栈和队列)
数据结构
流年如夢4 小时前
栈和列队(LeetCode)
数据结构·算法·leetcode·链表·职场和发展
qeen877 小时前
【数据结构】二叉树相关经典函数C语言实现
c语言·数据结构·c++·笔记·学习·算法·二叉树
良木生香8 小时前
【C++初阶】STL——List从入门到应用完全指南(1)
开发语言·数据结构·c++·程序人生·算法·蓝桥杯·学习方法
richard_yuu9 小时前
数据结构|二叉树高阶进阶-经典算法
数据结构·c++·算法
不知名的忻9 小时前
Dijkstra算法(朴素版&堆优化版)
java·数据结构·算法··dijkstra算法
YL2004042611 小时前
027合并两个有序链表
java·数据结构·算法·链表
Zephyr_011 小时前
java数据结构
java·数据结构
xieliyu.12 小时前
Java手搓二叉树:基础遍历与核心操作全解析
java·开发语言·数据结构·学习
期待のcode12 小时前
Redis数据类型
运维·数据结构·redis