平衡二叉树的定义
二叉查找树的性能要达到最高,树的高度就要最小;满二叉树和完全二叉树的高度都是最小,但是在插入或删除结点后维护其最小高度的代价较大。而平衡二叉树可以说是一种折中的办法,可以兼顾查找和维护性能。
平衡二叉树全称平衡二叉查找树,他是一颗满足一下条件的二叉查找树:
- 平衡因子的绝对值不超过1
- 左子树和右子树也满足上面的条件
解释: 平衡二叉树的平衡因子=左子树高度-右子树高度
平衡二叉树的失衡及调整
当平衡二叉树插入一个结点后,如果导致了某个结点发生了失衡(即平衡因子的绝对值大于1),这时候就需要对这颗进行调整使其继续满足平衡二叉树的特征。一般可以分为下面四种情况:
LL型 - 右旋调整
LL型是指在最小失衡子树(如图中结点A)的左孩子的左子树上插入了新的结点。其调整方案如图所示:
这种方式也被叫做右旋调整。
算法实现:
void R_Rotate(BBSTree &p) {BBSTree lc = p->lchild; // lc指向p结点的左孩子p->lchild = lc->rchild; // lc结点的右子树置为p结点的左子树lc->rchild = p; // 置p结点为lc结点的右孩子p = lc; // p指向新的根结点}
RR型 - 左旋调整
对于RR型,正好与LL型对称,对以A为根的最小失衡子树进行逆时针旋转(也称左旋调整),如图所示:
算法实现:
void L_Rotate(BBSTree &p) {BBSTree rc = p->rchild; //rc指向p结点的右孩子p->rchild = rc->lchild; //rc结点的左子树置为p结点的右子树rc->lchild = p; //置p结点为rc结点的左孩子p = rc; //p指向新的根结点}
LR型 - 左旋右旋调整
LR型指的是最小失衡子树的左孩子的右子树上插入了新的结点。处理办法:首先找到以A为根的最小失衡子树,以该子树的左孩子结点B为轴,对右子树结点C进行左旋调整,使之变为LL型。再以C为轴,对不平衡结点A进行右旋调整。
效果图:
RL型 - 右旋左旋调整
LR型指的是最小失衡子树的左孩子的右子树上插入了新的结点。处理办法如图所示,首先找到以A为根的最小失衡子树,以该子树的左孩子结点B为轴,对右子树结点C进行左旋调整,使之变为LL型。再以C为轴,对不平衡结点A进行右旋调整。
效果图:
对于上面这四种调整方案,最重要的是记住它们的调整思路而不是算法实现,算法实现其实是比较简单的,只是改变指针的指向即可。
平衡二叉树的插入
有了前面失衡及其调整的基础,在向平衡二叉树插入结点的时候就可以用来调整这颗平衡二叉树了,或者用来构建一棵新的平衡二叉树。构建或插入结点的递归算法思路如下:
- 若是空树,则插入的结点作为根结点,树的高度增加1
- 若插入的结点和根结点相等,则不能插入,直接返回
- 若插入结点小于根结点,并且左子树中的结点的值不等于当前要插入的值,那么就可以把这个结点插入到根结点的左子树,且左子树高度增加1,至于插入后是否需要调整平衡,需要分情况讨论:
- 若插入前根结点的平衡因子为-1,插入后变为0,整颗树的高度不变,无需调整
- 若插入前根结点的平衡因子为0,插入后变为1,整颗树的高度+1,无需调整
若插入前根结点的平衡因子为1,插入后变为2,需要调整,而且调整需要分2种情形:
(1)若左子树的根结点平衡因子为1,则属于LL型,需要右旋调整<br /> (2)若左子树的根结点平衡因子为-1

