对于而查找树来说序列{1,2,3,4,5} 会是一个右斜树,这样复杂度就是O(n),起不到使用二叉树查找树来进行数据查询优化的目的。于是需要对树进行调整:
使树的高度在每次插入元素后仍能保持O(logn)的级别;
于是就产生了平衡二叉树
平衡因子:左子树与右子树的高度之差称为该结点的平衡因子。
只要能随时保证每个结点平衡因子的绝对值不超过1,AVL的高度就始终能保持O(logn),
由于需要对每个结点都得得到平衡因子,因此需要在树的结构中加入一个变量height,来记录当前结点的为根结点的子树高度:
struct node
{
int data;//结点权值
int height;//为当前子树高度
tree L;
tree R;
};
获取结点root所在子树的当前高度:
int getHeight(tree root)
{
if (root == NULL) return 0;//空结点高度为0
return root->height;
}
根据平衡因子的定义,可以获取平衡因子:
int getBalanceFactor(tree root)
{
//左子树高度减去右子树的高度
return getHeight(root->L) - getHeight(root->R);
}
结点root所在子树的height等于其左子树的height与右子树的height的较大值加1,因此更新height可以如下写法:
void updataHeight(tree root)
{
root->height = max(getHeight(root->L), getHeight(root->R)) + 1;
}
平衡二叉树的基本操作:
1.查找操作:
int searchh(tree root, int x)
{
if (root == NULL) return 0;
if (root->data == x) return 1;
else if (root->data < x) searchh(root->R, x);
else searchh(root->L, x);
}
2,插入操作:
这个二叉查找树是有区别的,因为,需要考虑平衡因子,所以不能像二叉查找树那样直接插入。
这里引进了 左旋(L) 右旋(R)
L:
就是下图的A和B换位置,A,B换位置的同时,他们的儿子也要相应的根据平衡二叉树来进行变换,下面是变换规则
步骤:
1.让B的左子树成为A的右子树
2.让A成为B的左子树
3.让根节点设定为结点B
图中黑色填充代表真个过程中该部分的父节点发生了变化。
void L(tree &root)
{
tree temp = root->R;//root指向结点A,temp指向结点B
root->R = temp->L;//步骤1
temp->L = root;//步骤2
updataHeight(root);//更新结点A的高度
updataHeight(temp);//更新结点B的高度
root = temp;//步骤3
}
R:
既然有左旋那么就一定有右旋
如图:右旋
右旋步骤:
1.让A的右子树成为B的左子树
2.让B成为A的右子树
3.将根节点设定为结点A
void R(tree &root)
{
tree temp = root->L;
root->L = temp->R;
temp->R = root;
updataHeight(root);
updataHeight(temp);
root = temp;
}
二者可以发现就是代码R变成L,L变成R的区别
对于LL和LR的讨论(LL和LR不是左旋和右旋的意思):
按照上图讨论:
当结点A的左孩子的平衡因子是1时为LL型,是-1时为LR型。
先考虑LL型:
可以把以c为根节点的子树看作一个整体,然后以结点A作为root进行右旋
考虑LR型:
可以先忽略结点A,以结点c为root进行左旋,就可以把情况转化为LL型,然后按照上面的LL型的做法进行一次右旋即可。
同样的对于RR和RL型是一样的思路:
void insertt(tree &root, int x)
{
if (root == NULL) {
root = new node;
root->data = x;
root->height = 1;
root->R = root->L = NULL;
return;
}
if (x < root->data) {
insertt(root->L, x);
updataHeight(root);
if (getBalanceFactor(root) == 2) {
if (getBalanceFactor(root->L) == 1) {//LL型
R(root);
}
else if (getBalanceFactor(root->L) == -1) {//LR型
L(root->L);
R(root);
}
}
}
else {
insertt(root -> R, x);
updataHeight(root);
if(getBalanceFactor(root) == -2) {
if (getBalanceFactor(root->R) == -1) {//RR型
L(root);
}
else if (getBalanceFactor(root->R) == 1) {//RL型
R(root->R);
L(root);
}
}
}
}