AVL树----java版

一.AVL树是什么

在前面的学习中我们已经学习了二叉搜素树,二叉搜素树主要用于查询。二叉搜素树的查询效率为o(n),当树有序的时候二叉搜素树就变为一颗单分支的树,树的高度为n,所以最坏情况下时间复杂度为o(n)。
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

AVL树的特点:1.他的左右子树都是AVL树
2.左右子树高度之差不超过1(右子树减去左子树高度小于1)

二.AVL树节点的定义

class AVLTree {
   

    static class TreeNode {
   
        public int val;
        public int bf;//平衡因子
        public TreeNode left;//左孩子的引用
        public TreeNode right;//右子树的引用
        public TreeNode parent;//父亲节点的引用

        public TreeNode(int val) {
   
            this.val = val;
        }
    }

我们需要把AVL定义为三叉树,同时增加bf记录每个节点的平衡因子,通过获取节点的平衡因子来调节树的平衡。三叉结构增加一个指针指向父亲节点,可以更好的在增加节点时修改父亲节点的平衡因子。

三.AVL树的插入

AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:1. 按照二叉搜索树的方式插入新节点。2. 调整节点的平衡因子

 public boolean insert(int val) {
   
        TreeNode node = new TreeNode(val);
        if(root == null) {
   
            root = node;
            return true;
        }

        TreeNode parent = null;
        TreeNode cur = root;
        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;
            }
        }
        //cur == null
        if(parent.val < val) {
   
            parent.right = node;
        }else {
   
            parent.left = node;
        }
        //
        node.parent = parent;
        cur = node;

上述代码为二叉搜素树的插入,前面已经学习过,但注意相比于二叉搜素树AVL树多了每个节点的parent域必须指向父亲节点。
如果在插入节点时,插入的节点比父亲节点大,那么该节点在父亲节点的右分支,bf++,反之如比父亲节点小,应当在父节点的左分支,所以bf–。
在这里插入图片描述

 while (parent != null) {
   
            //先看cur是parent的左还是右  决定平衡因子是++还是--
            if(cur == parent.right) {
   
                //如果是右树,那么右树高度增加 平衡因子++
                parent.bf++;
            }else {
   
                //如果是左树,那么左树高度增加 平衡因子--
                parent.bf--;
            }

我们每插入一个节点都需要更新父亲节点的平衡因子,总共可分为三种情况:

1.如果更新后父亲节点的平衡因子为0,说明没有插之前父亲节点的平衡因子为1或者-1。在插入该节点后变为0,又说明正好插入矮的一边父亲节点因此平衡,此时树的高度不变,不用继续向上调整。
2.如果更新后平衡因子为1或者-1,说明未插入之前父亲节点的高度为0,插入后父亲节点变得不平衡,此时需要向上调整更新祖先节点的高度,最多会更新到根节点。
3.如果向上调整的过程中某个节点的平衡因子变为2或者-2此时该树不平衡,不是AVL树,我们需要调整这颗树使其成为AVL树,要将其进行旋转。

平衡因子为0时不需要调整直接返回:
在这里插入图片描述

平衡因子为1或者-1时需要向上调整
在这里插入图片描述
平衡因子为2或者-2时需要旋转:
在这里插入图片描述

  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;

四.AVL树的旋转

1.右旋

在这里插入图片描述
在这里插入图片描述

由于60节点的平衡因子为-2所以不满足AVL树的定义,需要对该节点进行旋转。左树比右树高,所以需要减少左树的高度增加右树的高度,简单的来说就是把30节点提上去,60节点压下来。为了完成该操作首先让60节点的左树链接40节点,然后30节点右边链接60节点把60节点压下来,在更改30节点和60节点的parent指针的指向。旋转后整棵树平衡,旋转前30节点和60节点的bf分别为-1和-2,旋转后树平衡了,所以还需要改30节点和60节点的bf为0。
代码实现:

private void rotateRight(TreeNode parent) {
   

        TreeNode subL = parent.left;
        TreeNode subLR = subL.right;

        parent.left = subLR;
        subL.right = paren
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值