BBST 与 AVL(插入、删除)

BBST (Balance Binary Search Tree) 平衡二叉搜索树

首先了解一下随机生成和随机组成的区别:

名称插入点的个数可生成BST树个数平均树高
随机生成NN!log2N
随机组成NCatalan(N)根号N

N个节点构成的二叉树,树高为log2N,称为理想平衡
N个节点构成的二叉树,树高渐进地接近log2N,称为适度平衡
适度平衡的BST称为BBST

等价变换旋转调整:Zig(右旋) Zag(左旋)
等价意味着中序遍历不变,节点之间的上下父子关系可变。

AVL (Adelson-Velsky-Landis Tree) 自适应平衡二叉搜索树

首先,我们在此处引入平衡因子
平衡因子定义为:平衡因子(v) = v的左子树高度 – v的右子树高度
AVL要满足所有节点的平衡因子不超过1也不小于-1

插入:

时间复杂度O(1)

单旋

若插入一个新的节点x后引发了部分节点的失衡,那么高度最低的失衡点g不会低于新插入节点的祖父。通过一次Zig变换或者Zag变换改变失衡节点g的状态,g恢复平衡后,x更高的祖先也将恢复平衡。不需要对其更高的祖先们再进行其他操作。

改变一个节点的失衡状态,便可以使整个树恢复平衡。

双旋

与单旋情况一样,高度最低的失衡点g不会低于新插入节点的祖父。经过两次Zig或Zag变换,使g恢复平衡。

删除:

时间复杂度O(logN)

单旋

删除单个节点x的时候,有可能首个失衡节点g就是x的父亲,此时通过一次Zig或Zag变换即可使g恢复平衡。但是此时,与插入操作不同的是,节点g的父亲以及更高的祖先可能会相继发生失衡,此时,需要逐个遍历祖先节点以判断其是否失衡,并处以相应的复恒处理即可。

改变一个节点的失衡状态,可能会引发整个树的失衡。

双旋

调用两次Zig或Zag变换即可。同样,也应逐个遍历祖先节点以判断其是否失衡,并处以相应的复恒处理即可。

说明

Zig和Zag变换方便了我们加深对AVL恢复平衡操作的理解,然而如果具体按照Zig和Zag编写代码进行左旋右旋的步骤是很复杂的。然而,令人高兴的是我们有更好的方式去实现恢复平衡的操作。在此,我们引入3+4重构的理念。可以说Zig和Zag只是辅助我们理解AVL的自适应变换,真正需要实现的代码是3+4重构

3+4重构:

可以理解为魔方的恢复操作。我们在恢复一个被打乱的魔方时,需要经过多次的旋转才可以将魔方恢复至初态。但是,在魔方生产车间,工人们是如何做的呢?工人们可不会没事闲的一个个去转动魔方,而是将魔方的各个部件按照初态的样子进行直接组装。相应的,AVL既然是为了使树恢复平衡,我们只需要把相关的节点拆分,重新进行组装即可

在对AVL树进行插入或删除操作时,我们需要找到最低高度的失衡节点g,并将它作为爷爷,对其祖孙三代g、p、v及各自对应的子树进行拆分和组装的操作。

具体操作:现在假设祖孙三个节点按照中序遍历的次序重命名为a、b、c,这三个节点对应的子树的根节点按照中序遍历的次序为T1、T2、T3、T4,现在我们只需按照T1、a、T2、b、T3、c 、T4的顺序重新组合成理想二叉树即可。同时不要忘记更新a、b、c三个节点的高度。(具体操作为,T1、T2作为a的左右子树,T3、T4作为c的左右子树,a、c作为b的左右子树)

此时,我们需要写出旋转函数rotate( ),其传入的参数为孙子节点v。在rotate(v)中定义其父亲节点p和祖父节点g。根据插入或者删除操作后,失衡二叉树属于的Zig-Zag类型,将g、p、v及各自对应的子树与a、b、c及T1、T2、T3、T4进行参数绑定即可完成相当于旋转的操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值