AVL树的基本操作

目录

AVL的概念:

节点高度:

新增节点高度:

平衡因子:

左旋:

右旋:

LR旋:

RL旋:

检查是否失衡:

新增节点:

删除节点:

完整代码:


AVL的概念:

* 二叉搜索树在插入和删除时,节点可能失衡
* 插入和删除操作时,需要调整树结构,使树再次平衡这就是自平衡的二叉搜索树
* avl是自平衡的二叉搜索树的一种

节点高度:

 private int height(AVLNode node){
        return node==null?0:node.height;
    }

新增节点高度:

private void updateHeight(AVLNode node){
        node.height=Integer.max(height(node.left),height((node.right)))+1;
    }

平衡因子:

private int bf(AVLNode node){
        return height(node.left)-height(node.right);
    }

左旋:

private AVLNode leftRotate(AVLNode node){
        AVLNode newRoot=node.right;
        AVLNode temp=newRoot.left;
        newRoot.left=node;
        node.right=temp;
        updateHeight(node);
        updateHeight(newRoot);
        return newRoot;
    }

右旋:

  private AVLNode rightRotate(AVLNode node){
        AVLNode newRoot=node.left;
        AVLNode temp=newRoot.right;
        newRoot.right=node;//上位
        node.left=temp;//换爹
        updateHeight(node);//这个高度需要变
        updateHeight(newRoot);//这两行的位置不能换,先更新低的高度,再更新高的高度
        return newRoot;
    }

LR旋:

private AVLNode leftRightRotate(AVLNode node){
        node.left=leftRotate(node.left);
        return rightRotate(node);
    }

RL旋:

private AVLNode rightLeftRotate(AVLNode node){
        node.right=rightRotate(node.right);
        return leftRotate(node);
    }

检查是否失衡:

private AVLNode isBalance(AVLNode node){
        if(node==null){
            return null;
        }
        if(bf(node)>1&&bf(node.left)>=0){//LL   =0:是左子树平衡,根节点失衡
            return rightRotate(node);
        }else if(bf(node)>1&&bf(node.left)<0){//LR
            return leftRightRotate(node);
        }else if(bf(node)<-1&&bf(node.right)>0){//RL
            return rightLeftRotate(node);
        } else if(bf(node)<-1&&bf(node.right)<=0){//RR  =0:是右子树平衡,根节点失衡 发生在删除时
            return leftRotate(node);
        }
        return node;
    }

新增节点:

  public void put(int key,Object value){
        root=doPut(root,key,value);
    }

    private AVLNode doPut(AVLNode root, int key, Object value) {//root :上一个节点
        //1.找到空位,新增节点
        if(root==null){
            return new AVLNode(key,value);
        }
        //2.key已存在,更新value
        if(key==root.key){
            root.value=value;
            return root;
        }
        //3.继续
        if(key<root.key){
            root.left=doPut(root.left,key,value);
        }else{
            root.right=doPut(root.right,key,value);
        }
        //4.更新高度
        updateHeight(root);
        //5.检查是否失衡
        return isBalance(root);
    }

删除节点:

public void remove(int key){
        root=doRemove(root,key);
    }

    private AVLNode doRemove(AVLNode root, int key) {
        //1.node==null,没找到
        if(root==null){
            return null;
        }
        //2没找到
        if(key<root.key){
            root.left=doRemove(root.left,key);//更新删除后剩余的
        }else if(key>root.key){
            root.right=doRemove(root.right,key);
        }else{
            //3.找到,删除节点 1)没有左右孩子 2)只有左孩子  3)只有右孩子 4)左右孩子都有
            if(root.left==null&&root.right==null){
                return null;
            }else if(root.left==null){
                root=root.right;  //为了继续下面的操作
            }else if(root.right==null){
                root=root.left;
            }else{
                AVLNode s=root.right;
                while(s.left!=null){//找后继节点
                    s=s.left;
                }
                //检查后继节点
                s.right=doRemove(root.right,s.key);
                s.left=root.left;
                root=s;
            }
        }
        //4.更新高度
        updateHeight(root);
        //5.检查是否失衡
        return isBalance(root);
    }

完整代码:


public class AVLTree {
    static class AVLNode{
        int key;
        Object value;
        AVLNode left;
        AVLNode right;
        int height=1;
        public AVLNode(int key,Object value){
            this.key=key;
            this.value=value;
        }

        public AVLNode(int key) {
            this.key = key;
        }

        public AVLNode(int key, Object value, AVLNode left, AVLNode right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
    //求节点的高度
    private int height(AVLNode node){
        return node==null?0:node.height;
    }
    //更新增删旋转的高度
    private void updateHeight(AVLNode node){
        node.height=Integer.max(height(node.left),height((node.right)))+1;
    }
    //平衡因子
    /*
    * 平衡的:0 1 -1
    * 不平衡: <-1 >1
    * */
    private int bf(AVLNode node){
        return height(node.left)-height(node.right);
    }
    //右旋  节点是要旋转的节点 返回值是新的根节点
    private AVLNode rightRotate(AVLNode node){
        AVLNode newRoot=node.left;
        AVLNode temp=newRoot.right;
        newRoot.right=node;//上位
        node.left=temp;//换爹
        updateHeight(node);//这个高度需要变
        updateHeight(newRoot);//这两行的位置不能换,先更新低的高度,再更新高的高度
        return newRoot;
    }
    //左旋
    private AVLNode leftRotate(AVLNode node){
        AVLNode newRoot=node.right;
        AVLNode temp=newRoot.left;
        newRoot.left=node;
        node.right=temp;
        updateHeight(node);
        updateHeight(newRoot);
        return newRoot;
    }
    //LR旋 先左旋右子树,再右旋根节点
    private AVLNode leftRightRotate(AVLNode node){
        node.left=leftRotate(node.left);
        return rightRotate(node);
    }
    //RL旋 先右旋左子树,再左旋根节点
    private AVLNode rightLeftRotate(AVLNode node){
        node.right=rightRotate(node.right);
        return leftRotate(node);
    }
    //检查是否失衡
    private AVLNode isBalance(AVLNode node){
        if(node==null){
            return null;
        }
        if(bf(node)>1&&bf(node.left)>=0){//LL   =0:是左子树平衡,根节点失衡
            return rightRotate(node);
        }else if(bf(node)>1&&bf(node.left)<0){//LR
            return leftRightRotate(node);
        }else if(bf(node)<-1&&bf(node.right)>0){//RL
            return rightLeftRotate(node);
        } else if(bf(node)<-1&&bf(node.right)<=0){//RR  =0:是右子树平衡,根节点失衡 发生在删除时
            return leftRotate(node);
        }
        return node;
    }
    AVLNode root;
    //put 新增节点
    public void put(int key,Object value){
        root=doPut(root,key,value);
    }

    private AVLNode doPut(AVLNode root, int key, Object value) {//root :上一个节点
        //1.找到空位,新增节点
        if(root==null){
            return new AVLNode(key,value);
        }
        //2.key已存在,更新value
        if(key==root.key){
            root.value=value;
            return root;
        }
        //3.继续
        if(key<root.key){
            root.left=doPut(root.left,key,value);
        }else{
            root.right=doPut(root.right,key,value);
        }
        //4.更新高度
        updateHeight(root);
        //5.检查是否失衡
        return isBalance(root);
    }
    //删除 remove
    public void remove(int key){
        root=doRemove(root,key);
    }

    private AVLNode doRemove(AVLNode root, int key) {
        //1.node==null,没找到
        if(root==null){
            return null;
        }
        //2没找到
        if(key<root.key){
            root.left=doRemove(root.left,key);//更新删除后剩余的
        }else if(key>root.key){
            root.right=doRemove(root.right,key);
        }else{
            //3.找到,删除节点 1)没有左右孩子 2)只有左孩子  3)只有右孩子 4)左右孩子都有
            if(root.left==null&&root.right==null){
                return null;
            }else if(root.left==null){
                root=root.right;  //为了继续下面的操作
            }else if(root.right==null){
                root=root.left;
            }else{
                AVLNode s=root.right;
                while(s.left!=null){//找后继节点
                    s=s.left;
                }
                //检查后继节点
                s.right=doRemove(root.right,s.key);
                s.left=root.left;
                root=s;
            }
        }
        //4.更新高度
        updateHeight(root);
        //5.检查是否失衡
        return isBalance(root);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就七天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值