目录
一、平衡二叉树的定义
平衡二叉树,简称平衡树(AVL树)——树上任一结点的左子树和右子树的高度之差不超过1。
结点的平衡因子=左子树高-右子树高。
typedef struct AVLNode{
int key;
int balance;
struct AVLNode *lchild,*rchild;
}AVLNode,*AVLTree;
二、平衡二叉树的插入
思考:在二叉排序树中插入新结点后,如何保持平衡?
注:每次调整的对象都是“最小不平衡子树”
三、调整最小不平衡子树A
四种情况:
①LL——在A的左孩子的左子树中插入导致不平衡
②RR——在A的右孩子的右子树中插入导致不平衡
③LR——在A的左孩子的右子树中插入导致不平衡
④RL——在A的右孩子的左子树中插入导致不平衡
四、调整最小不平衡子树(LL)
目标:1.恢复平衡;2.保持二叉排序树特性
二叉排序树的特性:左子树结点值<根节点值<右子树结点值
BL<B<BR<A<AR
LL平衡旋转(右单旋转)。由于在结点A的左孩子(L)的左子树(L)上插入了新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要一次向右的旋转操作。将A的左子树B向右上旋转代替A称为根节点,将A结点向右下旋转称为B的右子树的根结点,而B的原右子树则作为A结点的左子树。
五、调整最小不平衡子树(RR)
二叉排序树的特性:左子树结点值<根节点值<右子树结点值
AL<A<BL<B<BR
RR平衡旋转(左单旋转)。由于在结点A的右孩子(R)的右子树(R)上插入了新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要一次向左的旋转操作,将A的右孩子B向左上旋转代替A称为根结点,将A结点向左下旋转称为B的左子树的根结点,而B的原左子树则作为A结点的右子树
代码思路
实现f向右下旋转,p向右上旋转:
其中f是爹,p为左孩子,g为f他爹
①f->lchild = p->rchild;
②p->rchild = f;
③gf->lchild/rchild = p;
BL<B<BR<A<AR
实现f向左下旋转,p向左手旋转:
其中f是爹,p为右孩子,gf为f他爹
①f->rchild = p->lchild;
②p->lchild = f;
③gf->lchild/rchild = p;
AL<A<BL<B<BR
七、调整最小平衡子树(LR)
LR平衡旋转(先左后右双旋转)。由于在A的左孩子(L)的右子树(R)上插入新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋转后又旋转。先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置,然后再把该C结点向右上旋转提升到A结点的位置
BL<B<CL<C<CR<A<AR
两种情况:
①
②
八、调整最小不平衡子树(RL)
RL平衡旋转(先右后左双旋转)。由于在A的右孩子(R)的左子树(L)上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋转后左旋转。先将A结点的右孩子B的左子树的根节点C向右上旋转提升到B结点的位置,然后再把该C结点向左上旋转提升到A结点的位置
两种情况:
①
②
九、调整最小不平衡子树
总结:只有左孩子才能右上旋转,只有右孩子才能左上旋转
插入操作导致“最小不平衡子树”高度+1,经过调整后高度恢复
十、练习
1.RR型
2.RL型
3.LR型
十、查找效率分析
若树高为h,则最坏情况下,查找一个关键字最多需要对比h次,即查找操作的时间复杂度不可能超过O(h)