AVL树

AVL树

平衡因子:某节点的左右子树高度差。

特点

  • 每个叶子结点的平衡因子只能是1,0,-1,如果超过1代表失衡。
  • 每个节点的左右子树高度差不超过1
  • 搜索,添加,删除的时间复杂度是O(logn)

image-20210116153746237

上图的不是AVL树,AVL树是平衡二叉搜索树的一种实现,平衡二叉搜索树的实现有AVL树和红黑树。

他们都能在添加删除之后都能自己调整到平衡状态。

左旋操作(RR)

image-20210116155626421

g.right=p.left;
p.left=g;

让p变成这棵树的根节点。

在操作的时候注意发生parent属性改变的节点。(T1,p,g)

右旋操作(LL)

image-20210116160349575

g.left=p.right;
p.right=g;


protected static class Node<E>{
    E element;
    Node<E> left;
    Node<E> right;
    Node<E> parent;
    public Node(E element,Node<E> parent){
        this.element = element;
        this.parent = parent;
    }
}

private static class AVLNode<E> extends Node<E>{
    public AVLNode(){
        super(element,parent);
    }
    int height=1;
    
    private int balanceFactor(){
        int leftHeghit = left==null?0:((AVLNode<E>)left).height;
        int rightHeghit = right==null?0:((AVLNode<E>)right).height;
    }
}
//判断是否平衡,平衡因子绝对值小于等于1代表平衡
private boolean isBalanced(Node node){
    return Math.abs(((AVLNode<E>)node).balanceFactor)<=1;
}

//添加之后恢复平衡
protected void afterAdd(Node<E> node){
    while((node=node.parent)!=null){
        if(isBalanced(node)){
            //如果平衡,更新节点的高度
            updateHeight(node);
        }else{
            //恢复平衡
            reblanced(node);
            break;
        }
    }
}

private void reblanced(Node<E> grand){
    Node<E> parent = ((AVLNode<E>)grand).tallerChild();
    Node<E> node = ((AVLNode<E>)parent).tallerChild();
    if(parent.isLeftChild()){
        if(node.isLeftChild()){ //LL
            //右旋
            rotateRight(grand);
        }else{//LR
            //左旋
            rotateLeft(parent);
            //右旋
            rotateRight(grand);
        }
    }else{
        if(node.isLeftChild()){ //RL
            //右旋
            rotateRight(parent);
            //左旋
            rotateLeft(grand);
        }else{//RR
            //右旋
            rotateRight(grand);
        }
    }
}
//左旋
private void rotateLeft(Node<E> grand){
    Node<E> parent = grand.right;
    Node<E> child = parent.left;
    grand.right = child;
    parent.left = grand;
   
    //让parent变成子树的根节点
    parent.parent = grand.parent;
    if(grand.isLeftChild()){
        grand.parent.left = parent;
    }else if(grand.isRightChild()){
        grand.parent.right=parent;
    }else{
        //grand是根节点
        root = parent;
    }
    //更新child的parent
    if(child!=null){
        child.parent = grand;
    }
    //更新grand 的parent
    grand.parent = parent;
    //更新parent和grand的高度
    updateHeight(parent);
    updateHeight(grand);
    
}

//右旋
private void rotateRight(Node<E> grand){
    Node<E> parent = grand.right;
    Node<E> child = parent.left;
    grand.left = child;
    parent.right = grand;
    //剩下的步骤和左旋一样,更新三者的parent,更新高度,因此抽取共有部分
    afterRotate(grand,parent,child);
}

private void afterRotate(Node<E> grand,Node<E> parent,Node<E> child){
    //让parent变成子树的根节点
    parent.parent = grand.parent;
    if(grand.isLeftChild()){
        grand.parent.left = parent;
    }else if(grand.isRightChild()){
        grand.parent.right=parent;
    }else{
        //grand是根节点
        root = parent;
    }
    //更新child的parent
    if(child!=null){
        child.parent = grand;
    }
    //更新grand 的parent
    grand.parent = parent;
    //更新parent和grand的高度
    updateHeight(parent);
    updateHeight(grand);
}

//更新高度就是将当前高度+1,当前高度就是左右子树较大的高度
private void updateHeight(){
     int leftHeghit = left==null?0:((AVLNode<E>)left).height;
        int rightHeghit = right==null?0:((AVLNode<E>)right).height;
    this.height = Math.max(leftHeight,rightHeight)+1;
}

//删除节点后调整二叉搜索树的平衡
public void afterRemove(Node<E> node){
     while((node=node.parent)!=null){
        if(isBalanced(node)){
            //如果平衡,更新节点的高度
            updateHeight(node);
        }else{
            //恢复平衡
            reblanced(node);
            
        }
    }
}

public void remove(E element){
    remove(node(element));
}


AVL树添加节点时可能会导致所有祖先节点都失衡。

只要让高度最低的失衡节点恢复平衡,整棵树就会恢复平衡。O(1)

AVL树删除操作可能导致父节点或祖先节点失衡(只有一个),让父节点恢复平衡后,可能导致更高层的祖先节点失衡。最多需要O(logn)次调整。

平均时间复杂度

搜索:O(logn)

添加:O(logn),仅需要O(1)常数级别的操作

删除:O(logn),最多需要logn次旋转

先左旋后右旋 LR操作

先对P进行左旋,再对g进行右旋

image-20210116220635087

RL操作,先对p进行右旋转,再对g进行左旋转。

image-20210116220925380

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值