二叉排序树见:https://blog.youkuaiyun.com/weixin_51450101/article/details/123172688?spm=1001.2014.3001.5501
1. 平衡二叉排序树
平衡二叉排序树又称AVL树。一棵平衡二叉排序树或者是空树,或者是具有下列性质的二叉排序树:
① 左子树与右子树的高度之差的绝对值小于等于1;
② 左子树和右子树也是平衡二叉排序树。
引入平衡二叉排序树的目的是为了提高查找效率。
平衡因子:结点的左子树深度与右子树深度之差。显然对一棵平衡二叉排序树而言,其所有结点的平衡因子只能是-1、0或1。当在一个平衡二叉排序树上插入一个结点时,有可能导致失衡,即出现绝对值大于1的平衡因子,如2和-2。
类型定义
typedef int DataType;
/*平衡二叉排序树的类型定义*/
typedef struct node {
DataType data;
int bf; //结点的平衡因子
struct node* lchild, * rchild;
}AVLNode, * AVLTree;
2. 失衡类型及调整方法
2.1 LL型
假设最低层失衡结点为A,在结点A的左子树的左子树插入新结点S导致失衡。由A和B的平衡因子容易容易推知,BL、BR以及AR的深度相同。为了恢复平衡并保持二叉排序树特性,可按下图方式进行调整:
/*LL型调整代码*/
//1 旋转结点实现平衡
A->lchild = B->rchild;
B->rchild = A;
//2 调整平衡因子
A->bf = 0; B->bf = 0;
//3 将当前调整完的子树接到原树上
if (FA == NULL) //FA为A原来的父指针
*avlt = B;
else if (A == FA->lchild) FA->lchild = B;
else FA->rchild = B;
2. LR型
假设最低层失衡结点为A,在结点A的左子树的右子树插入新结点S导致失衡。这里假设在CL下插入S,由A、B、C的平衡因子推知,CL与CR深度相同,BL与AR深度相同,且BL、AR比CL、CR的深度大1。为了恢复平衡并保持二叉排序树特性,可按下图方式进行调整:
/*LR型调整代码*/
//1 旋转结点实现平衡
C = B->rchild;
B->rchild = C->lchild;
A->lchild = C->rchild;
C->lchild = B;
C->rchild = A;
//2 调整平衡因子
if (S->data < C->data) {
A->bf = -1;
B->bf = 0;
C->bf = 0;
}
else if (S->data > C->data) {
A->bf = 0;
B->bf = 1;
C->bf = 0;
}
else {
A->bf = 0;
B->bf = 0;
}
//3 将当前调整完的子树接到原树上
if (FA == NULL) //FA为A原来的父指针
*avlt = C;
else if (A == FA->lchild)
FA->lchild = C;
else
FA->rchild = C;
}
3. RR型
RR型和LL型对称。假设最低层失衡结点为A,在结点A的右子树的右子树插入新结点S导致失衡。由A和B的平衡因子容易容易推知,BL、BR以及AL的深度相同。为了恢复平衡并保持二叉排序树特性,可按下图方式进行调整: