平衡二叉树

什么是平衡二叉树

wiki:https://en.wikipedia.org/wiki/AVL_tree

1.它是一颗空树,即是没有节点的树,或者是具有以下性质的二叉树:

2.树的左子树和右子树的高度之差(平衡因子)的绝对值不能超过1,并且左子树和右子树也是平衡二叉树,如此循环。

其中,平衡因子:左子树的高度 - 右子树的高度,所以左子树高度比右子树高度小,则平衡因子就是负数,反之为正数,相等则为0。

如何维护平衡二叉树

由于一般二叉树可能变成最坏的情况,变成一条链表,这样查找节点时时间的复杂度将会变得很大。
由于平衡二叉树的特点,可以避免这样最坏的情况,平衡二叉树的查找时间复杂度为O(logn)。
虽然平衡二叉树的查找比较有优势,但是每次插入或者删除节点时,需要维护它平衡二叉树的特点不变,即在插入或者删除节点时,需要有左旋或者右旋的操作来维护平衡的特点。

从树的叶子往树的根逐个节点检查二叉树各个子树的平衡因子。

右旋

当一颗树(这里说到的一颗树可以是对整颗树,也可以是一颗树中其中的一部分的子树)的左子树的高度比右子树的高度大于1时,则需要右旋操作。

例如:

显然4的平衡因子大于1了,为了保持平衡那我们就这样做:让4节点的左孩子指向3的右子树(此时为NULL),让3的右孩子指向4,让树根指向3,如图

这种操作我们规定为右旋操作,此图是以4为根进行旋转。

假设这颗树(左子树lTree, 树根root, 右子树rTree),以树根root为支点,进行右旋。
将root转为lTree的根节点,root也就变成lTree的一部分,也可以这样理解,这样的话那么左子树的高度就增加了1,处理完左子树之后,就需要选出这颗树新的根节点,新的根节点需要从rTree中选出,根节点需要比左子树都大(也即是比左子树的所有节点都小),比右子树都小,则只要从右子树中找出最小的节点作为树新的根节点即可,找出右子树中的最左边的节点作为新的根节点,如果没有最左边的节点,则提取右子树的根节点,这样右子树的高度就减少了1,而之前左子树高度增加了1,整颗树的高度就趋向于平衡了。
注意: 如果根root与它的右孩子的平衡因子的符号不同,例如根为正右孩子为负,或者根为负右孩子为正,则先以在右孩子为支点左旋,然后再以根root右旋。

左旋

当一颗树(这里说到的一颗树可以是对整颗树,也可以是一颗树中其中的一部分的子树)的右子树的高度比左子树的高度大于1时,则需要左旋操作。

例如


显然节点4不平衡了。那我们就把4的右孩子7的左子树(此时为NULL),让7的左孩子指向4,让3的右孩子指向7,如图:

我们规定此操作为左旋操作,此图是以4为根进行旋转。

假设这颗树(左子树lTree, 树根root, 右子树rTree),以树根root为支点,进行左旋。

将root转为rTree的根节点,root也就变成rTree的一部分,也可以这样理解,这样的话那么右子树的高度就增加了1,处理完右子树之后,就需要选出这颗树新的根节点,新的根节点需要从lTree中选出,根节点需要比右子树都大(也即是比右子树的所有节点都小),比左子树都大,则只要从左子树中找出最大的节点作为树新的根节点即可,找出左子树中的最右边的节点作为新的根节点,如果没有最右边的节点,则提取左子树的根节点,这样左子树的高度就减少了1,而之前右子树高度增加了1,整颗树的高度就趋向于平衡了。

现在我们在原来基本上插入10节点:


显然节点9不平衡,且是右边高,那我们左旋吧,左旋后的效果是上图右图所示。显然这是不对的,10比11小,但在11的右孩子上。(根本原因是9和11的平衡因子符号不同)。

由于9和11的平衡因子符号不同,需要先以9的右孩子11为中心进行右旋,

然后再以9为中心左旋。

如果根root与它的左孩子的平衡因子的符号不同,例如根为正左孩子为负,或者根为负左孩子为正,则先以在左孩子为支点右旋,然后再以根root左旋。

参照: http://lib.csdn.net/article/datastructure/9204

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值