为避免树的高度增长过快,降低二叉排序树的性能,规定在插入和删除二叉树结点时,要保证任意结点的左、右子树高度差的绝对值不超过1,将这样的二叉树称为平衡二叉树(Balanced Binary Tree),简称平衡树。
结点的平衡因子 = 左子树高-右子树高。
定义结点左子树与右子树的高度差为该结点的平衡因子,则平衡二叉树结点的平衡因子的值只可能是一-1、0或1。
我们要思考在二叉排序树中插入新结点后,如何保持平衡?
插入新结点后,查找路径上的所有结点都有可能受到影响,使得平衡因子的值会超过1。那我们怎么办呢?
如上图,首先从插入点67往回找到第一个不平衡结点70,调整该结点作为根的子树,这个子树我们称为是 “最小不平衡子树” 。
接下来我们只需将最小不平衡子树调整为平衡即可,中序为67->68->70。
导致不平衡的插入总结有4种情况。
在结点A的左孩子(L)的左子树(L)上插入了新结点,导致不平衡。如上图,插入之后 B的左子树BL高为H+1,其他子树高是H,根节点A的平衡因子为2,出现不平衡情况。这时候我们就要进行一次向右的旋转操作:
设指针f指向根结点A,指针p指向A的左子树B结点,gf指针指向A的父结点;
实现f向右下旋转,p向右上旋转;
其中f是爹,p为左孩子,gf为f他爹;
f->lchild = p->rchild;
p->rchild = f;
gf->lchild/rchild = p;
由于BL<B<BR<A<AR,左旋、右旋操作后可以保持二叉排序树的特性。
为什么要假定所有子树的高度都是H?
在结点A的右孩子®的右子树® 上插入了新结点,导致不平衡。如上图,插入之后 B的右子树BR高为H+1,其他子树高是H,根节点A的平衡因子=AL-(BR+1)=H-(H+1+1)=-2,出现不平衡情况。这时候我们就要进行一次向左的旋转操作:
设指针f指向根结点A,指针p指向A的左子树B结点,gf指针指向A的父结点;
实现f向左下旋转, p向左上旋转;
其中f是爹,p为右孩子,gf为f他爹;
f->rchild = p->lchild;
p->lchild = f;
gf->lchild/rchild = p;
由于AL<A<BL<B<BR,左旋、右旋操作后可以保持二叉排序树的特性。
如上图,在A的左孩子B的右子树(BR)上插入新结点,A的平衡因
子=BR+1-AR=2,导致以A为根的子树失去平衡。我们可以拆分来看,以B为根节点的最小不平衡子树来看,是一个RR操作,需要一次左旋操作;作为根节点A的最小不平衡子树来看,是一个LL操作,需要一次右旋操作。
因此,调整最小不平衡子树(LR)需要进行两次旋转操作:(先左后右双旋转):
如上图,在A的右孩子B的左子树(BL)上插入新结点,A的平衡因
子=AL-(BL+1)=-2,导致以A为根的子树失去平衡。我们可以拆分来看,以B为根节点的最小不平衡子树来看,是一个LL操作
,需要一次右旋操作;作为根节点A的最小不平衡子树来看,是一个RR操作
,需要一次左旋操作。
因此,调整最小不平衡子树(RL)需要进行两次旋转操作:(先右后左双旋转):
总之在插入操作中,只有将最小不平衡子树调整平衡,则其他祖先结点都会自然而然的恢复平衡。
若树高为h,则最坏情况下,查找一个关键字最多需要对比 h 次,即查找操作的时间复杂度不可能超过 O(h)。
平衡二叉树——树上任一结点的左子树和右子树的高度之差不超过1。
假设以 Nh 表示深度为h的平衡树中含有的最少结点数。则有n0 = 0, n1 = 1, n2 = 2,并且有Nh = Nh-1 + Nh−2 + 1,可以证明含有n个结点的平衡二叉树的最大深度为O(log2n) ,平衡二叉树的平均查找长度为O(log2n)。
例如:T4 = T3 +T2 +1 = 9+4+1 = 14
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_44775255/article/details/120732197
内容来源于网络,如有侵权,请联系作者删除!