数据结构——快速掌握LL旋转LR旋转以及RL旋转RR旋转
todo
平衡二叉树的平衡因子只会有三种值:-1,0,1。 在平衡二叉树插入或者删除一个结点时,很可能破坏其平衡性,为了调整平衡性,因此需要执行旋转。
平衡因子
平衡因子:某结点左右子树的高度差值
【例】如下图
一个结点的平衡因子=该节点左子树深度-该节点右子树深度
于是:
5的结点平衡因子就是 3 - 2 = 1;
2的结点平衡因子就是 1 - 2 = -1;
4的结点平衡因子就是 1 - 0 = 1;
6的结点平衡因子就是 0 - 1 = -1;
叶子结点没有子树,于是叶子结点的平衡因子都是0
平衡二叉树和不平衡的二叉树的对比:
对于平衡二叉树产生了不平衡之后,如何进行平衡调整?
注意:每次都是按照最小不平衡子树进行调整
LL平衡旋转
当在某个结点的左孩子的左子树新插入了结点,需要进行LL平衡旋转,向右旋
如下图:(方框部分是对子树进行了抽象封装,同时这些子树的高度都是H,并且假设它们都是平衡的,下同)
上图说明:
(a) 初始状态是平衡状态,A,B结点的平衡因子分别是1,0;并且它们之间有一个潜在的大小关系:BL < B < BR < A < AR
(b) B的左子树插入了一个结点,导致A结点的平衡因子变为2,此时不满足二叉平衡树的要求(平衡因子只能是-1,0,1)
由于A结点的平衡因子为2,说明左边大,右边小,为了保持平衡,需要右旋。
执行右旋后,B结点的右子树会变成A结点的左子树,使得仍然满足大小关系:BL < B < BR < A < AR
*注意二叉排序树的特性:左子树结点值 < 根结点值 < 右子树结点值
( c ) 由于B的左子树增加了一个结点,使得高度加了1,此时B的平衡因子为0,又重新变成了平衡二叉树。
【例】如下图
插入9之后,变得不平衡,找到最小不平衡子树,由于不平衡发生在15结点的左孩子的左子树,于是需要对15的左孩子10执行LL平衡旋转,即向右旋,10替换15的位置,将15变成10的右孩子
RR平衡旋转
当在某个结点的右孩子的右子树插入了结点,需要进行RR平衡旋转,向左旋
B结点左旋到A结点的位置,为保证各节点大小顺序不变,B的左子树变为A的右子树
【例】
如上图所示,插入结点90后,产生了不平衡,于是先找到最小不平衡子树
由于不平衡发生在以66为根结点的右孩子的右子树,因此需要执行RR平衡旋转,即就是向左旋。
让不平衡结点66的右孩子68左旋,68替代66,为保证各结点的大小顺序不发生改变,将68的左孩子变成你66的右孩子。
LR平衡旋转
当在某个结点的左孩子的右子树插入了结点,需要进行LR平衡旋转,先向左旋,再向右旋
如上图所示,先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置,将C的左子树变为B的右子树;
然后再把C结点向右旋转提升到A结点的位置,将C的右子树变为A的左子树
调整过后需要满足:BL<B<CL<C<CR<A<AR
【例1】
如上图所示,插入结点 57之后发生了不平衡,
最小不平衡子树为整颗树,发生不平衡的位置是 66 结点的左孩子 50 的右子树,因此需要执行LR平衡操作,针对 50 的右结点 60 先左旋,60 替代 50,50成为 60 的左孩子,原本可以60的左子树成为 50 的右子树
接下来右旋 ,60 代替 66 ,将 60 的右孩子变为66的左孩子
[例2]
最小不平衡子树如虚线框所示,发生在75这一结点,原因是75的左孩子38插入了右结点,因此执行LR旋转 ,找到 75 左孩子38的第一个右孩子 51,先左旋,51 提换 38,51没有子树不用为子树重新定位 ,然后 51 再右旋,51 替换 75,75 成为51的右孩子
RL平衡旋转
当在某个结点的右孩子的左子树插入了结点,需要进行RL平衡旋转,先向右旋再向左旋
先将A结点的右孩子B的左子树的根结点C向右旋转提升到B结点的位置,将C的右子树变为B的左子树;
然后再把C结点左旋提升到A结点的位置,将C的左子树变为A的右子树;
调整过后需要满足:AL<A<CL<C<CR<B<BR
【例】
插入结点 63 后,最小不平衡树仍然是整颗树,不平衡情况发生在50的右孩子的左子树 , 因此需要执行RL平衡旋转
先对结点 66 先进行右旋,66 替换 68,66的右孩子 67 成为 68 的左孩子;
然后对 66 左旋 ,66 替换 50,66 的左孩子成为 50 的右孩子;
熟练之后可以一步到位,如上图所示,66 的左子树直接给 50,右孩子直接给68, 66 往上提
为什么要按“最小不平衡子树”进行调整?
插入操作导致某个子树高度+1,当调整这个不平衡子树后,高度恢复为原来的高度后,重新恢复到平衡,其它祖先结点也自然恢复到了平衡
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)