自平衡二叉查找树总结

目录

1.概念

2AVL树

树的旋转

1.左旋

2.右旋

3.左双旋转

4.右双旋转

树的平衡


1.概念

在介绍自平衡二叉查找树之前,先说一下二叉树,这里就简单列一下概念来自《数据结构和算法分析》

二叉树:是一棵树,每个节点不能多于两个儿子

二叉查找树:树中所有项都可以被排序,即树中每个节点x,它的左子树所有项都小于x,它的右子树所有项都大于x。

自平衡的二叉查找树:根据某些平衡条件保证树的深度(avl和红黑树)

2AVL树

AVL树严格保障树的高度达到某种条件:左子树和右子树高度相差不能大于1。但是每次插入或者删除的时候都有可能破坏平衡条件,解决的方法是树的旋转。

树的旋转

1.左旋

如图,对k1进行左旋,即将k1变成左节点,k2为根,k2的左节点变成k1的右节点

代码示例:

    private AvlNode leftRate(AvlNode k1) {
        AvlNode k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k2.height = Math.max(k1.height, height(k2.right))+1;
        k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
        return k2;
    }

2.右旋

如图:对k2进行右旋,即将k2变为右节点,k1为根,k1的右节点变为k2的左节点。

代码示例:

    private AvlNode rightRate(AvlNode k2) {
        AvlNode k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k1.height = Math.max(k2.height, height(k1.left))+1;
        k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
        return k2;
    }

3.左双旋转

先对k3进行右旋,在对k1进行左旋。

代码示例

    private AvlNode leftDoubleRate(AvlNode k1) {
        k1.right = rightRate(k1.right);
        return leftRate(k1);
    }

4.右双旋转

对k1进行左旋,然后对k3进行右旋。

代码示例:

    private AvlNode rightDoubleRate(AvlNode k3) {
        k3.left = rightRate(k3.left);
        return leftRate(k3);
    }

树的平衡

了解了树的旋转,我们讨论什么情况下,如何进行平衡

插入

在插入之后,破坏了AVL平衡条件,我们要平衡这棵树,我们将不满足平衡条件的节点叫x,呢么有四种情况会破坏:

1.向x的左儿子的左子树进行插入.

对x进行右旋

2.向x的左儿子的右子树进行插入.

对x右双旋转

3.向x的右儿子的左子树进行插入.

对x左双旋转

4.向x的右儿子的右子树进行插入.

对x左旋

代码示例:

    //向t插入x
    private AvlNode insert(int x, AvlNode t) {
        //如果t为空
        if (t == null) {
            return new AvlNode(x, null, null);
        }
        //如果x小于节点,将x插入至左节点
        if (x < t.element) {
            t.left = insert(x, t.left);
        } else {//否则插入至右节点
            t.right = insert(x, t.right);
        }
        //开始平衡
        return balance(t);
    }

    //左右节点高度相差的最大值,大于此值则表示不平衡
    private final static int ALLOWED_IMBALANCE = 1;

    private AvlNode balance(AvlNode t) {
        if (t == null) {
            return t;
        }
        if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {//左侧高失去平衡
            if (height(t.left.left) > height(t.right)) {//左左 右旋
                t = rightRate(t);
            }else{//左右 右双旋
                t = rightDoubleRate(t);
            }
        }else{//右侧高
            if (height(t.left.left) > height(t.right)) {//右左 左双旋
                t = leftDoubleRate(t);
            }else{//右右 左旋
                t = leftRate(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

删除

    private AvlNode remove(int x, AvlNode t) {
        //如果t为空 什么都不做
        if (t == null) {
            return t;
        }
        //如果x小于节点,将x插入至左节点
        if (x < t.element) {
            t.left = remove(x, t.left);
        } else if (x > t.element) {//否则插入至右节点
            t.right = remove(x, t.right);
        } else if (t.left != null && t.right != null) {//如果有两个孩子 将右子树最小值代替x删除右子树最小值
            t.element = findMin(t.right);
            t.right = remove(x, t.right);
        } else {
            t = (t.left == null) ? t.left : t.right;
        }
        return balance(t);
    }

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值