js实现自平衡树 AVL tree

本文介绍了JavaScript实现AVL树的过程,包括插入和删除节点的特殊情况。在插入节点后,通过检查节点的平衡因子来判断是否需要进行平衡操作,如单旋转(LL, RR)和双旋转(RL, LR)。在删除节点时,根据节点的平衡因子和子节点情况决定是否进行旋转以保持平衡。文章提供了相关的代码示例,详细解释了自平衡树的平衡调整策略。" 86384877,7610454,Python+unittest+requests接口自动化测试实践与问题解析,"['Python编程', '测试工具', '自动化测试', '接口测试', 'unittest框架']
摘要由CSDN通过智能技术生成

1. 笔记

节点高度:Math.max(左节点高度, 右节点高度)+1
平衡因子:左节点高度 - 右节点高度,节点内数字表示当前节点的平衡因子。
平衡操作共有四种情况。
1. 向右的单旋转 LL: 当前节点的左节点比右节点重,当前节点的左节点的左节点比右节点重。
在这里插入图片描述
2. 向左的单旋转 RR: 当前节点的右节点比左节点重,当前节点的右节点的右节点比左节点重。
3. 向左的双旋转 RL: 当前节点的右节点比左节点重,当前节点的右节点的左节点比右节点重。
先对 当前节点的右节点 进行一次向右的单旋转,在对当前节点进行向左的单旋转。
4. 向右的双旋转 LR: 当前节点的左节点比右节点重,当前节点的左节点的右节点比左节点重。
先对 当前节点的左节点 进行一次向左的单旋转,在对当前节点进行向右的单旋转。
在这里插入图片描述
基于二叉搜索树的insert方法,AVL与之不同的则是,在每次插入后,我们需要检测插入后根节点的平衡因子,是否为0 1 -1三个数的其中一个。不是的话,则需要对当前树进行调整。
表格中数字是节点的平衡因子

根节点 根的左子节点 根的右子节点 操作 描述
1 - - - 平衡
0 - - - 平衡
-1 - - - 平衡
2 1 平衡 向右的单旋转 LL
2 0 平衡 向右的单旋转 LL
2 -1 平衡 向右的双旋转 LR
-2 平衡 1 向左的双旋转 RL
-2 平衡 -1 向左的单旋转 RR
-2 平衡 0 向左的单旋转 RR

insertNode

insert(value) {
   
	super.insert(value)
	return this.checkIsBalance()
}

removeNode

remove(value) {
   
	super.remove(value)
	return this.checkIsBalance()
}

checkIsBalance

checkIsBalance() {
   
	this.root = this._changeToBalance(this.root)
	return this
}

插入节点的特殊情况

为下图的左边的树,添加一个节点,使其不平衡。但我们发现,此时平衡因子所属情况与之前所描述的不同。此时我们需要进行递归,先对根节点的左节点进行平衡操作LL,完成后在对根节点进行平衡操作。这是根节点的平衡因子等于2的情况。当然等于-2的情况与之原理相同。
在这里插入图片描述
连续插入左节点,在自平衡过程中,会报错,因为this.root.left.right为null。故在LLRR使用try catch语句,处理异常。右节点:this.root.right为null,高度为-1
在这里插入图片描述
在右侧插入节点(红色),导致原树不平衡。只需做一次向左的单旋转RR,即可平衡。插入左侧节点时,原理一致。
在这里插入图片描述

删除节点的特殊情况

我们在看另外一种情况,下图删除了一个节点。左树平衡,右树不平衡。但根节点(平衡因子)为2,左子节点为0,右子节点平衡的情况之前没有讨论过。我们可以直接对其进行一次向右的单旋转即可平衡。当然,根节点为2,左子节点平衡,右子节点为0的情况与之原理相同。
在这里插入图片描述
在这里插入图片描述
_changeToBalance

_changeToBalance(node) {
   
     switch(this.getBalanceFactory(node)){
   
        case 2:
            const factoryLeft = this.getBalanceFactory(node.left)
            if([0,1].indexOf(factoryLeft) !== -1 || factoryLeft > 2){
   
                console.info('2 0 1')
                node = this.rotationLL(node)
            }else if(factoryLeft === -1){
   
                console.info('2 -1')
                node = this.rotationLR(node)
            }else if(factoryLeft === 2){
   
                console.info('2 2')
                node.left = this._changeToBalance(node.left)
            }else if(factoryLeft === -2){
   
                console.info('2 -2')
                node.left = this._changeToBalance(node.left)
            }
            return node
        case -2:
            const factoryRight = this.getBalanceFactory(node.right)
            if([0,1].indexOf(factoryRight) !== -1){
   
                console.info('-2 0 1')
                node = this.rotationRL(node)
            }else if(factoryRight === -1 || factoryRight < -2){
   
                console.info
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值