AVL Tree与BST
由于AVL树本身就是一颗自平衡的BST,因此其的删除比起BST仅仅多了删除后平衡的调整
查找:
AVL树中一定不存在两个值大小相同的节点
从AVL树根开始向下搜索,根据意图删除值与当前节点值大小关系进行下一步操作:
1、 当前节点值大于意图删除值,保存当前节点并在当前节点的左子树中继续查找意图删除值
2、 当前节点值小于意图删除值,保存当前节点并在当前节点的右子树中继续查找意图删除值
3、 当前节点值等于意图删除值,准备进行删除
查找的过程中保存当前节点,是为了便于回溯并修改、判断可能被删除影响的节点的平衡因子
删除:
根据意图删除节点的子树个数可以将删除分为三种情况:
1、 意图删除的节点没有子树(叶子节点)
2、 意图删除的节点有且仅有一个子树
3、 意图删除的节点既有左子树又有右子树
与BST的删除相同,这三种情况又可以概括为两种情况:
1、 意图删除节点最多存在一个子树
2、 意图删除节点存在两个子树
情况1的删除非常简单,就不解释了,情况2下需要将删除有两个子树的节点转换为删除仅有一个子树的节点:
使用意图删除节点的最大左子树值或者最小右子树值替换意图删除值,再删除替换值所在节点
删除完成后立即根据之前查找时保存的节点信息回溯(修改平衡因子并立即判断平衡因子)
调整平衡:
AVL树是否平衡是由平衡因子决定的,修改完平衡因子后应立即判断平衡因子,根据平衡因子的情况作下一步操作,回溯到的节点的平衡因子修改后立即判断平衡因子值:
1、 如果平衡因子为1 / -1则说明以其为根的树高度并没有改变,仅仅是其一个子树矮了,以其为子树的树(与以其为根的树)依旧是平衡的,无需继续向上回溯
2、 如果平衡因子为0则说明以其为根的树高度改变,其子树高度改变,但无法确定以其为子树的树的高度是否改变,需继续向上回溯以修改平衡因子并继续判断
3、 如果平衡因子为2 / -2则说明以回溯到的节点为根的子树(与以其为子树的树)已经不平衡了。应立即旋转来使树平衡
和插入一样,旋转使需要分类的
根据平衡因子为2 / -2的节点(假设其被指针Ptr指向)判断其左子树高还是右子树高,使指针指向其较高的一棵子树的树根(假设其被指针Ps指向):
1、 如果其较高一颗子树根的平衡因子为0,则向降低树高的方向进行一次单旋转来达到平衡的目的
2、 如果其较高一颗子树的平衡因子与其平衡因子同号,向降低树高的方向进行一次单旋转来达到平衡的目的
3、 如果其较高一颗子树的平衡因子与其平衡因子异号,需要执行双旋转以使树再次平衡
完成旋转后可能需要继续向上回溯,毕竟旋转操作使原来以平衡因子为 2 / -2为根的整颗
树的高度降低了,可能导致以其为子树的树不平衡,是否继续向上回溯需要判断平衡因子。
平衡因子的计算:
1、Ps所指节点平衡因子为0,Ptr所指节点平衡因子为2 / -2,即此种情况下Ps的左右子树高度相同,Ps所指节点所在的子树(Ptr的子树)与Ptr的另一子树的高绝对值为2:设Ps所指节点的左子树高位LN,右子树高为RN ,则有LN== RN, Ps所指节点所在子树(Ptr的子树)高为LN+ 1, Ptr另一子树高为LN+ 1 – 2,旋转后Ptr所指节点的较高子树高度为LN (旋转时Ps的某一子树给了Ptr,且给的子树高度必然大于Ptr的另一子树高度),较矮子树高位LN + 1 – 2,因此Ptr所指节点的平衡因子为1,以Ptr所指节点为树根的树高LN + 1,Ps左子树高LN,因此整棵树(节点Ps)的平衡因子为-1
如上图:上图是删除后旋转前AVL树的示意图,被删除的节点位于P所在子树,图中虚线连接的节点是否存在不被关心
令Ptr为整棵树的树根,且其BF为2,Ps为较高的一颗子树,p为其另一颗子树;
设Ps左子树Pl高LN,其右子树高RN,要满足Ps的BF为0,必须有LN == RN,因为Ps为Pl的双亲,有Ps高LN + 1,Ptr为Ps的双亲,可知Ptr高LN + 1 + 1,又因为删除导致P所在子树被缩短,Ptr的平衡因子为2,故P高LN + 1 - 2
旋转后ptr到如今Pr的位置,且Pr成为Ptr的左子树,Ptr成为Ps的右子树,因为Pr比p高LN – (LN + 1 - 2),因此旋转后的Ptr平衡因子为1,旋转之后Ptr高LN + 1,旋转前后Ps左子树Pl不受影响,依旧高LN,但旋转后Ps的右子树Ptr的高度为LN + 1,Pl比Ptr高LN –(Ln + 1),因此旋转后Ps的平衡因子为-1
其余情况同理可得
来源:CSDN
作者:早起的虫儿灬
链接:https://blog.csdn.net/Hello_World_LVLcoder/article/details/72233394