平衡二叉树(Balanced Binary Tree):空树或者任一结点左、右子树高度差的绝对值不超过1,即|BF(T)| <= 1
平衡因子(Balance Factor,简称BF):BF(T)=hL-hR,其中hL和hR分别为T的左、右子树的高度
插入结点或删除结点时,当BF的值大于2或者小于2的时候,使用不同的旋转,使得二叉树平衡:
1. 每插入一个结点都要检验一次树,是否是平衡树
2. 若是不是平衡树,从树的最深处开始旋转
3. 根据平衡因子的正负和添加结点的位置,使用不同的旋转方式:(此旋转方式是固定的)
若结点的BF = 2时,且结点的左子树结点的BF = 1时,使用RotateLL(BF=2的结点)
若结点的BF = 2时,且结点的左子树结点的BF = -1时,使用RotateLR(BF=2的结点)
若结点的BF = -2时,且结点的左子树结点的BF = -1时,使用RotateRR(BF=-2的结点)
若结点的BF = -2时,且结点的左子树结点的BF = 1时,使用RotateRL(BF=-2的结点)
完整的代码:
#include <iostream>
#include <cstdio>
using namespace std;
// AVLTree平衡二叉树(Balanced Binary Tree)/高度平衡的二叉查找树
// 插入、删除
typedef int DataType;
typedef struct node{
DataType data;
int bf; // 平衡因子
struct node *lchild, *rchild;
}AVLNode, *AVLTree;
// 右单旋转(LL旋转): *a的左子树的左子树上 插入新结点
void RotateLL(AVLNode *&a)
{
AVLNode *b = a->lchild;
a->lchild = b->rchild;
b->rchild = a;
b->bf = a->bf = 0;
a = b;
}
// 左单旋转(RR旋转): *a的右子树的右子树上 插入新结点
void RotateRR(AVLNode *&a)
{
AVLNode *b = a->rchild;
a->rchild = b->lchild;
b->lchild = a;
b->bf = a->bf = 0;
a = b;
}
// 先左后右双旋转(LR旋转): *a的左子树的右子树上 插入新结点
void RotateLR(AVLNode *&a)
{
AVLNode *b = a->lchild, *c = b->rchild;
b->rchild = c->lchild; // 左单旋转
c->lchild = b; // 左单旋转
if(c->bf <= 0)
b->bf = 1;
else
b->bf = 0;
a->lchild = c->rchild; // 右单旋转
c->rchild = a; // 右单旋转
if(c->bf == -1)
a->bf = 0;
else
a->bf = -1;
c->bf = 0;
a = c;
}
// 先右后左双旋转(RL旋转): *a的右子树的左子树上 插入新结点
void RotateRL(AVLNode *&a)
{
AVLNode *b = a->rchild, *c = b->lchild;
b->lchild = c->rchild; // 右单旋转
c->rchild = b; // 右单旋转
if(c->bf >= 0)
b->bf = -1;
else
b->bf = 0;
a->rchild = c->lchild; // 左单旋转
c->lchild = a; // 左单旋转
if(c->bf == 1)
a->bf = 0;
else
a->bf = 1;
c->bf = 0;
a = c;
}
// 先序递归遍历
void PreOrder(AVLTree root)
{
if(root != NULL)
{
printf("%4d", root->data);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
void PreBF(AVLTree root) // 先序遍历平衡因子
{
if(root != NULL)
{
printf("%4d", root->bf);
PreBF(root->lchild);
PreBF(root->rchild);
}
}
void InOrder(AVLTree root) // 中序递归遍历
{
if(root != NULL)
{
PreOrder(root->lchild);
printf("%4d", root->data);
PreOrder(root->rchild);
}
}
// 计算树的平衡因子
int count(AVLNode *r)
{
if(r->lchild == NULL && r->rchild == NULL)
{
r->bf = 0;
return 1;
}
else
{
int lhigh, rhigh;
if(r->lchild != NULL)
{
lhigh = count(r->lchild);
}
else
lhigh = 0;
if(r->rchild != NULL)
{
rhigh = count(r->rchild);
}
else
rhigh = 0;
r->bf = lhigh - rhigh; // 因子 = 左子树高度 - 右子树高度
if(lhigh > rhigh)
return lhigh + 1;
else
return rhigh + 1;
}
}
// 一个结点一个结点地添加/删除,然后调整,所以平衡因子不会超过2/-2
// 在root树种,添加值为x的结点,并且调整成为平衡二叉树
AVLNode* InsertAndBalance(AVLTree &root, DataType x)
{
AVLNode *s, *p, *f;
if(root == NULL)
{
root = new AVLNode;
if(root == NULL)
return NULL;
root->data = x;
root->bf = 0;
root->lchild = NULL;
root->rchild = NULL;
return root;
}
else
{
if(x > root->data)
{
root->rchild = InsertAndBalance(root->rchild, x);
count(root); // 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子)
if(root->bf == 2) // 如果不平衡,进行旋转
{
if(root->lchild->bf == 1)
RotateLL(root);
else if(root->lchild->bf == -1)
RotateLR(root);
count(root);
}
else if(root->bf == -2)
{
if(root->rchild->bf == -1)
RotateRR(root);
else if(root->rchild->bf == 1)
RotateRL(root);
count(root);
}
}
else if(x < root->data)
{
root->lchild = InsertAndBalance(root->lchild, x);
count(root); // 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子)
if(root->bf == 2) // 如果不平衡,进行旋转
{
if(root->lchild->bf == 1)
RotateLL(root);
else if(root->lchild->bf == -1)
RotateLR(root);
count(root);
}
else if(root->bf == -2)
{
if(root->rchild->bf == -1)
RotateRR(root);
else if(root->rchild->bf == 1)
RotateRL(root);
count(root);
}
}
}
return root;
}
// 在root树种,删除结点x,并且调整成为平衡二叉树
AVLNode* RemoveAndBalance(AVLTree &root, DataType x)
{
AVLNode *s, *p, *f;
if(root == NULL)
{
return root;
}
else
{
if(x > root->data)
{
root->rchild = RemoveAndBalance(root->rchild, x);
count(root); // 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子)
if(root->bf == 2) // 如果不平衡,进行旋转
{
if(root->lchild->bf == 1)
RotateLL(root);
else if(root->lchild->bf == -1)
RotateLR(root);
count(root);
}
else if(root->bf == -2)
{
if(root->rchild->bf == -1)
RotateRR(root);
else if(root->rchild->bf == 1)
RotateRL(root);
count(root);
}
}
else if(x < root->data)
{
root->lchild = RemoveAndBalance(root->lchild, x);
count(root); // 修改结点的bf值,并返回高度(此处可以优化,需要重新递归求平衡因子)
if(root->bf == 2) // 如果不平衡,进行旋转
{
if(root->lchild->bf == 1)
RotateLL(root);
else if(root->lchild->bf == -1)
RotateLR(root);
count(root);
}
else if(root->bf == -2)
{
if(root->rchild->bf == -1)
RotateRR(root);
else if(root->rchild->bf == 1)
RotateRL(root);
count(root);
}
}
else if(x == root->data)
{
AVLNode *s, *f;
if(root->lchild == NULL && root->rchild == NULL) // 叶子的时候
{
delete root;
return NULL;
}
else if(root->lchild == NULL && root->rchild != NULL)
{
s = root->rchild;
delete root;
return s;
}
else if(root->lchild != NULL && root->rchild == NULL)
{
s = root->lchild;
delete root;
return s;
}
else if(root->lchild != NULL && root->rchild != NULL)
{
s = root->lchild;
if(s->rchild != NULL)
{
while(s->rchild != NULL)
{
f = s;
s = s->rchild;
}
f->rchild = NULL;
root->data = s->data;
if(s->lchild != NULL)
{
if(f->data > s->lchild->data)
f->lchild = s->lchild;
else
f->rchild = s->lchild;
}
}
else // 左子树没有右结点时
{
root->data = s->data;
root->lchild = s->lchild;
}
delete s;
return root;
}
}
}
return root;
}
int main()
{
int high;
AVLNode *s, *f;
AVLTree root = NULL;
InsertAndBalance(root, 53);
InsertAndBalance(root, 17);
InsertAndBalance(root, 9);
InsertAndBalance(root, 45);
InsertAndBalance(root, 23);
InsertAndBalance(root, 78);
InsertAndBalance(root, 65);
InsertAndBalance(root, 66);
InsertAndBalance(root, 67);
//InsertAndBalance(root, 94);
//InsertAndBalance(root, 81);
//InsertAndBalance(root, 88);
//high = count(root);
//cout << "Tree high is " << high << endl;
cout << "数值: ";
PreOrder(root);
cout << endl;
cout << "因子: ";
PreBF(root);
cout << endl << endl;
RemoveAndBalance(root, 45);
RemoveAndBalance(root, 9);
cout << "先序遍历: ";
PreOrder(root);
cout << endl;
cout << "中序遍历: ";
InOrder(root);
cout << endl;
cout << "平衡因子: ";
PreBF(root);
cout << endl << endl;
RemoveAndBalance(root, 17);
RemoveAndBalance(root, 53);
InsertAndBalance(root, 94);
cout << "先序遍历: ";
PreOrder(root);
cout << endl;
cout << "中序遍历: ";
InOrder(root);
cout << endl;
cout << "平衡因子: ";
PreBF(root);
cout << endl << endl;
return 0;
}
运行结果: