目录
一、AVL树简介
1.1 AVL树具有的性质
1、左子树与右子树的高度之差的绝对值小于等于1。
2、左子树和右子树也是平衡二叉排序树。
1.2 平衡因子
平衡因子(balance factor):结点的左子树深度与右子树深度之差。
1.3 失衡类型及调整方法
1、LL型
2、LR型
3、RR型
4、RL型
二、算法
2.1 初始化
{
AVLTree S, A, FA, p, fp, B, C;
/* 生成待插结点 */
S = (AVLTree)malloc(sizeof(AVLTNode));
S->key = K;
S->lchild = S->rchild = NULL;
S->bf = 0;
if (*avlt == NULL) {
*avlt = S;
return;
}
/* 初始化各指针 */
A = *avlt;
FA = NULL;
p = *avlt;
fp = NULL;
}
2.2 查找插入位置
while (p != NULL) { /* 因为插入位置最终为叶结点 */
if (p->key == K) { /* 若存在关键字等于key的元素,则放弃插入 */
free(S);
return;
}
if (p->bf != 0) { /* 使A为最低层失衡结点 */
A = p;
FA = fp;
}
fp = p;
if (K < p->key)
p = p->lchild;
else
p = p->rchild;
}
2.3 插入新结点
if (K < fp->key)
fp->lchild = S;
else
fp->rchild = S;
2.4 更新所有结点的平衡因子
/* 确定旋转点B,同时更新A的平衡因子 */
if (K < A->key) {
B = A->lchild;
A->bf = A->bf + 1;
} else {
B = A->rchild;
A->bf = A->bf - 1;
}
/* 更新B到S的路径上各结点的平衡因子(原值均为0)*/
p = B;
while (p != S) {
if (K < p->key) {
p->bf = 1;
p = p->lchild;
} else {
p->bf = -1;
p = p->rchild;
}
}
2.5 调整算法
1、LL型
if (A->bf == 2 && B->bf == 1) {
/* 顺时针旋转 */
B = A->lchild;
A->lchild = B->rchild; //B的右子树成为A的左子树
B->rchild = A; //A成为B的右子树
/* 更新平衡因子 */
A->bf = 0;
B->bf = 0;
/* 更新结点关系 */
if (FA == NULL)
*avlt = B;
else if (A == FA->lchild)
FA->lchild = B;
else
FA->rchild = B;
}
2、LR型
if (A->bf == 2 && B->bf == -1) {
B = A->lchild;
C = B->rchild;
/* 逆时针旋转 + 顺时针旋转 */
B->rchild = C->lchild;
A->lchild = C->rchild;
C->lchild = B;
C->rchild = A;
/* 更新平衡因子 */
if (S->key < C->key) {
A->bf = -1;
B->bf = 0;
C->bf = 0;
} else if (S->key > C->key) {
A->bf = 0;
B->bf = 1;
C->bf = 0;
} else {
A->bf = 0;
B->bf = 0;
}
/* 更新结点关系 */
if (FA == NULL)
*avlt = C;
else if (A == FA->lchild)
FA->lchild = C;
else
FA->rchild = C;
}
3、RR型
if (A->bf == -2 && B->bf == -1) {
/* 逆时针旋转 */
B = A->rchild;
A->rchild = B->lchild;
B->lchild = A;
/* 更新平衡因子 */
A->bf = 0;
B->bf = 0;
/* 更新结点关系 */
if (FA == NULL)
*avlt = B;
else if (A == FA->lchild)
FA->lchild = B;
else
FA->rchild = B;
}
4、RL型
if (A->bf == -2 && B->bf == 1) {
B = A->rchild;
C = B->lchild;
/* 顺时针旋转 + 逆时针旋转 */
B->lchild = C->rchild;
A->rchild = C->lchild;
C->lchild = A;
C->rchild = B;
/* 更新平衡因子 */
if (S->key < C->key) {
A->bf = 0;
B->bf = -1;
C->bf = 0;
} else if (S->key > C->key) {
A->bf = 1;
B->bf = 0;
C->bf = 0;
} else {
A->bf = 0;
B->bf = 0;
}
/* 更新结点关系 */
if (FA == NULL)
*avlt = C;
else if (A == FA->lchild)
FA->lchild = C;
else
FA->rchild = C;
}
三、总结
平衡二叉排序树插入操作的算法思想:
1、查找插入位置,同时记录离插入位置最近的可能失衡结点A;
2、插入新结点S;
3、确定旋转点B,同时更新A的平衡因子;
4、更新B到S的路径上各结点的平衡因子(原值必为0,否则A将下移);
5、根据A、B的平衡因子判断是否失衡以及失衡类型,并做相应处理。