avl树的学习

二叉树搜索树的时间复杂度 是O(logn) 就是二叉树的高度
    二叉搜索树的缺点:
    1 当有序添加元素时退化成链表
    2 删除节点的时候也会退化成链表
    平衡二叉搜索树:当节点数量固定的时候,左右子树的高度越接近,这颗二叉树就越平衡
    
    改进二叉搜索树
    首先,节点的添加和删除时无法限制的,
    接着,在节点的添加、删除操作之后,想办法让二叉搜索树恢复平衡(减少树的高度)
    如果接着继续调整节点的位置,完全可以达到理想平衡,但是付出的代价比较大
    如果调整的次数比较多,反而增加了时间复杂度
    总结:用尽量少的调整次数达到适度平衡就可以
    经典的平衡二叉树
    avl树、红黑树
    平衡因子:某节点的左右子树的高度差
    特点:
    每个节点的平衡因子只可能是1 0 -1 
    每个节点的左右子树的高度差不超过1 
    搜索、添加、删除的时间复杂度是O(logn)
    
    添加导致的失衡:
    可能会导致所有的祖先节点都失衡,但是只要让高度最低的失衡节点恢复平衡,整棵树就平衡了
    父节点不会失衡,非祖先节点不会失衡,
    
    ll 右边旋转 单旋   ll的意思是在失衡节点的左边左边
    rr 左边旋转 单旋
    LR 双旋 先左边,后边右边
    RL 双旋 先右边 后左边      
    总结: 相同字母反,不同字母同
    
    删除导致的失衡:
    可能会导致父节点或者祖父节点失衡,但是只有一个能失衡,如果删除导致父节点失衡了,那么这个删除的节点一定是比较短的
    让父节点恢复平衡后,可能会导致更高的祖先节点失衡,但是最多需要ologn次调整

package com.xk.algorithm.tree.avl;

import com.xk.algorithm.tree.binary.BinarySearchTree;

import java.util.Comparator;

/**
 * avl树
 * ll 右旋转
 * rr 左旋转
 * lr 先左旋转后右边旋转
 * rl 先右边旋转然后再左边
 * 旋转都是成为局部根节点
 *
 * @param <E>
 */
public class AvlTree<E> extends BinarySearchTree<E> {

    public AvlTree() {
        this(null);
    }

    /**
     * 有参构造函数
     *
     * @param comparator 比较器
     */
    public AvlTree(Comparator<E> comparator) {
        super(comparator);
    }

    @Override
    protected void afterAdd(Node<E> node) {
        while ((node = node.parent) != null) {
            if (isBalanced(node)) {
                //更新高度
                updateHeight(node);

            } else {
                //恢复平衡  当前节点一定是不平衡的,一定是平衡最低的
                rebalance(node);
                break;
            }

        }
    }

    private void rotate(
            Node<E> r,
            Node<E> a, Node<E> b, Node<E> c,
            Node<E> d,
            Node<E> e, Node<E> f, Node<E> g) {
        d.parent = r.parent;
        if (((AvlNode<E>) r).isLeftChild()) {
            r.parent.left = d;
        } else if (((AvlNode<E>) r).isRightChild()) {
            r.parent.right = d;
        } else {
            root = d;
        }

        //a - b - c
        b.left = a;
        if (a != null) {
            a.parent = b;
        }
        if (c != null) {
            c.parent = b;
        }
        b.right = c;

        updateHeight(b);

        //e - f -g
        f.left = e;
        if (e != null) {
            e.parent = f;
        }
        if (g != null) {
            g.parent = f;
        }
        f.right = g;

        updateHeight(f);
        //b-d-f
        d.left = b;
        d.right = f;
        b.parent = d;
        f.parent = d;
        updateHeight(d);
    }

    private void rebalance(Node<E> grand) {
        // 确定node parent grand  Parent 节点是 比较高的那个
        Node<E> parent = ((AvlNode<E>) grand).tallerChild();
        Node<E> node = ((AvlNode<E>) parent).tallerChild();
        //判断方向
        if (((AvlNode<E>) parent).isLeftChild()) {
            if (((AvlNode<E>) node).isLeftChild()) { //LL
//                rotateRight(grand);
                rotate(grand,node.left,node,node.right,parent,parent.right,grand,grand.right);
            } else { //LR
//                rotateLeft(parent);
//                rotateRight(grand);

                rotate(grand,grand.left,parent,node.left,node,node.right,grand,grand.right);
            }
        } else {
            if (((AvlNode<E>) parent).isLeftChild()) { //RL
//                rotateRight(parent);
//                rotateLeft(grand);

                rotate(grand,grand.left,grand,node.left,node,node.right,parent,parent.right);
            } else { //RR
//                rotateLeft(grand);
                rotate(grand,grand.left,grand,parent.left,parent,node.left,node,node.right);
            }

        }

    }

    @Override
    protected void afterRemove(Node<E> node) {
        while ((node = node.parent) != null) {
            if (isBalanced(node)) {
                //更新高度
                updateHeight(node);

            } else {
                //恢复平衡  当前节点一定是不平衡的,一定是平衡最低的
                rebalance(node);
            }

        }
    }

    private void rotateLeft(Node<E> grand) {
        Node<E> parent = grand.right;
        Node<E> child = parent.left;
        grand.right = child;
        parent.left = grand;

        afterRotate(grand, parent, child);

    }

    private void rotateRight(Node<E> grand) {
        Node<E> parent = grand.left;
        Node<E> child = parent.right;

        grand.left = child;
        parent.right = grand;
        afterRotate(grand, parent, child);
    }

    private void afterRotate(Node<E> grand, Node<E> parent, Node<E> child) {
        //让parent成为根节点
        parent.parent = grand.parent;
        if (((AvlNode<E>) grand).isLeftChild()) {
            grand.parent.left = parent;
        } else if (((AvlNode<E>) grand).isRightChild()) {
            grand.parent.right = parent;
        } else {//这个是根节点
            root = parent;
        }
        //更新child的parent
        if (child != null) {
            child.parent = grand;
        }

        //更新grand的parent
        grand.parent = parent;

        //更新高度 先更新矮的
        updateHeight(grand);
        updateHeight(parent);
    }

    protected Node<E> createNode(E element, Node<E> parent) {
        return new AvlNode<>(element, parent);
    }


    private boolean isBalanced(Node<E> node) {

        return Math.abs(((AvlNode<E>) node).balanceFactor()) <= 1;
    }

    private void updateHeight(Node<E> node) {
        ((AvlNode<E>) node).updateHeight();
    }


    private static class AvlNode<E> extends Node<E> {

        int height = 1;

        /**
         * 构造函数
         * 没有传递进来左右子树,是因为这两个可能为空
         *
         * @param element 当前节点存储的值
         * @param parent  当前节点的父节点
         */
        public AvlNode(E element, Node<E> parent) {
            super(element, parent);
        }

        public int balanceFactor() {
            int leftHeight = left == null ? 0 : ((AvlNode<E>) left).height;
            int rightHight = right == null ? 0 : ((AvlNode<E>) right).height;
            return leftHeight - rightHight;
        }

        public void updateHeight() {
            int leftHeight = left == null ? 0 : ((AvlNode<E>) left).height;
            int rightHight = right == null ? 0 : ((AvlNode<E>) right).height;
            height = 1 + Math.max(leftHeight, rightHight);
        }

        /**
         * 返回左右子树中比较高的
         * 如果相同高度,则返回相同方向的
         *
         * @return
         */
        public Node<E> tallerChild() {
            int leftHeight = left == null ? 0 : ((AvlNode<E>) left).height;
            int rightHight = right == null ? 0 : ((AvlNode<E>) right).height;
            if (leftHeight > rightHight) return left;
            if (leftHeight < rightHight) return right;
            return isLeftChild() ? left : right;
        }

        public boolean isLeftChild() {
            return parent != null && this == parent.left;
        }

        public boolean isRightChild() {
            return parent != null && this == parent.right;
        }
    }
}

    
    
        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值