AVL树的实现

本文详细介绍了AVL树的实现,包括其特性、失衡与重平衡算法。失衡时,通过单旋和双旋策略恢复平衡,确保插入和删除操作在O(logn)时间内完成。统一重平衡算法简化了处理流程,保持了AVL树的高度平衡。
摘要由CSDN通过智能技术生成

前面笔者介绍了二叉搜索树的一般实现平衡二叉树的实现原理
本篇文章将继续前文的平衡搜索树来介绍一种具体的平衡搜索树—AVL树。

AVL树的特性

AVL树中,对于任一节点V,其左右子树的高度差不能超过1。这个高度差定义为平衡因子。

为了判断AVL树的平衡性,在沿用前文的平衡二叉树的模版代码中,需要添加如下方法:

public Boolean isAvlBalanced(TreeNode node) {
        //获取平衡因子
        int balance = node.right.height - node.left.height;

        return balance > 2 && balance < -2; 
    }

失衡和重平衡

AVL树与常规的二叉搜索树一样,也应支持插入、删除等动态修改操作。但经过这类操作之后,节点的高度可能发生变化,以致于不再满足AVL树的条件。

观察下图的插入操作,在对图(b)一个AVL树插入’M’,于是,节点’N’、’R’和’G’ 都将失衡。类似地,删除’Y’之后, 也会如图(a)所示导致节点’R’的失衡。

这里写图片描述

如此因节点x的插入或删除而暂时失衡的节点,构成失衡节点集,记作失衡节点集UT(x)。请注意,若x为被摘除的节点,则UT(x)仅含单个节点; 但若x为被引入的节点,则UT(x)可能包含多个节点。
从对UT(x)的分析入手,分别介绍使失衡搜索树重新恢复平衡的调整算法。

节点插入失衡的恢复算法

不难看出,新引入节点x后,UT(x)中的节点都是x的祖先,且高度不低于x的祖父。以下,将其中的最深者记作g(x)—最深者即为高度最小的节点。在x与g(x)之间的通路上,设p为g(x)的孩子,v为p的孩子。注意, 既然g(x)不低于x的祖父,则p必是x的真祖先。

首先,需要找到如上定义的g(x)。为此,可从x出发沿parent指针逐层上行并核对平衡因子, 首次遇到的失衡祖先即为g(x)。既然原树是平衡的,故这一过程只需O(logn)时间。

既然g(x)是因x的引入而失衡,则p和v的高度均不会低于其各自的兄弟。因此,可在g(x)的左右孩子中寻找高度最高的节点p,用同样的方法在节点p的左右孩子中寻找节点最高的孩子v。

确定g(x),p,v三个节点后,将根据三个节点的联接方向,采用不同的局部调整方案,分述如下:

单旋

这里写图片描述

如上图(a)所示,设v是p的右孩子,p是g的右孩子。这种情况必是在v的子树中插入的新的节点x,使得g失衡,图(a)的阴影部分为插入x的节点,其兄弟为空。采用前文平衡二叉树的实现原理中的逆时针zag已g为轴旋转之后,使得g重新平衡。旋转后的结果图(b)所示。根据搜索树的等价原理来看。a,b两树的等价的。

同理,如果v是p的左孩子,p是g的左孩子。则可通过顺时针zig来重平衡。

双旋

这里写图片描述

如上图(a)所示,设节点v是p的左孩子,而p是g的右孩子。

这种情况,也必是由于在子树v中插入了新节点x,而致使g不再平衡。同样地,在图中以虚线联接的每一对灰色方块中,其一对应于新节点x,另一为空。

此时,可先做p为轴的顺时针旋转,得到如图(b)所示的一棵等价二叉搜索树。

再做g为轴的逆时针旋转zag,得到如图(c)所示的另一棵等价二叉搜索树。
此类分别以父子节点为轴、方向互逆的连续两次旋转,合称“双旋”。可见,经如此调整之后,g亦必将重新平衡。不难验证,通过zag(p)和zig(g)可以处理对称的情况。

无论单旋或双旋,经局部调整之后,不仅g(x)能够重获平衡, 而且局部子树的高度也必将复原。这就意味着,g(x)以上所有祖先的平衡因子亦将统一地复原,也意味着在AVL树中插入新节点后,仅需不超过两次旋转,即可使整树恢复平衡。

AVL树中节点的插入:

这段代码中的3+4算法即在本文后面

    /**
     * 添加子节点
     * @throws Exception 
     */
    public TreeNode addNode(Double data) {
        TreeNode inTree = this.search(data);

        if(inTree.data != null) {
            return inTree;
        }

        inTree
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值