AVL树是平衡的二叉查找树。也是高度平衡的二叉查找树。每个节点的左子树的高度与右子树的高度的差的绝对值小于等于1.
AVL树的基本操作包括:
- 首先包括旋转操作:左旋(逆时针),右旋(顺时针),左—右旋转(先左旋,后右旋),右—左旋转(先右旋,后左旋)。
- 右旋
void RotaeRR(AvlTree* &avl) {
if (!avl)
return;
else {
auto ptr = avl->lchild;
avl->lchild = ptr->rchild;
ptr->rchild = avl;
avl = ptr;
avl->height = max(Getheight(avl->lchild), Getheight(avl->rchild)) + 1;
ptr->height = max(Getheight(ptr->lchild), avl->height) + 1;
}
}
左旋和右旋是镜像对称的,所以不在讨论。
2.左—右旋转
void RotaeLR(AvlTree* &avl) {
if (!avl)
return;
else {
RotaeLL(avl->rchild);
RotaeRR(avl);
}
}
- 节点的高度。
int Getheight(AvlTree* &avl) {
if (avl == nullptr)
return -1;
else
return avl->height;
}
int max(int a, int b) {
return a > b ? a : b;
}
- 插入操作。AVL树的插入操作和Bst树的插入操作很相似,无非就是在插入中要通过旋转保持树的平衡性。
第三种情况和第四种情况关于上面两种情况镜像对称。
void Insert(AvlTree* &avl, ElemType X) {
int rightheight = 0, leftheight = 0;
if (!avl) {
avl = new AvlTree;
avl->element = X;
avl->height = 0;
avl->lchild = avl->rchild = nullptr;
}
else {
if (avl->element > X) {
Insert(avl->lchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((leftheight - rightheight) > 1) {
if (avl->lchild->element > X)
RotaeRR(avl);
else
RotaeLR(avl);
}
}
else if (avl->element < X) {
Insert(avl->rchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((rightheight - leftheight) > 1) {
if (avl->rchild->element < X)
RotaeLL(avl);
else
RotaeRL(avl);
}
}
}
avl->height = max(Getheight(avl->lchild), Getheight(avl->rchild)) + 1;
}
- 删除操作。AVL树的删除操作与Bst树比较相似,无非就是在删除中要通过旋转保持树的平衡性。
void Delete(AvlTree* &avl, ElemType X) {
int rightheight = 0, leftheight = 0;
int rightheight_ = 0, leftheight_ = 0;
AvlTree* temp = nullptr;
if (!avl)
return;
else if (avl->element > X) {
Delete(avl->lchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((rightheight - leftheight) > 1) {
rightheight_ = Getheight(avl->rchild->rchild);
leftheight_ = Getheight(avl->rchild->lchild);
if (rightheight_ > leftheight_)
RotaeLL(avl);
else
RotaeRL(avl);
}
}
else if (avl->element < X) {
Delete(avl->rchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((leftheight - rightheight) > 1) {
rightheight_ = Getheight(avl->lchild->rchild);
leftheight_ = Getheight(avl->lchild->lchild);
if (rightheight_ < leftheight_)
RotaeRR(avl);
else
RotaeLR(avl);
}
}
else if (avl->element == X) {
temp = avl;
if (avl->lchild != nullptr && avl->rchild != nullptr) {
temp = FindMin(avl->rchild);
avl->element = temp->element;
Delete(avl->rchild, avl->element);
}
else if (avl->lchild == nullptr)
avl = avl->rchild;
else if (avl->rchild == nullptr)
avl = avl->lchild;
else
delete temp;
}
}
第三种情况和第四种情况与上面情况镜像对称。
AVL树的上面几种操作比较难理解,其他都相对比较简单。完整代码如下:
#include<iostream>
#include<vector>
typedef struct TreeNode AvlTree;
typedef int ElemType;
struct TreeNode {
ElemType element;
AvlTree* lchild;
AvlTree* rchild;
int height;
};
int Getheight(AvlTree* &avl) {
if (avl == nullptr)
return -1;
else
return avl->height;
}
int max(int a, int b) {
return a > b ? a : b;
}
AvlTree* Find(AvlTree* &avl, ElemType X) {
if (!avl)
return nullptr;
else if (avl->element > X)
avl->lchild = Find(avl->lchild, X);
else if (avl->element < X)
avl->rchild = Find(avl->rchild, X);
else if (avl->element == X)
return avl;
}
AvlTree* FindMax(AvlTree* &avl) {
if (!avl) {
while (avl->rchild != nullptr)
avl = avl->rchild;
}
return avl;
}
AvlTree* FindMin(AvlTree* &avl) {
if (!avl) {
while (avl->lchild != nullptr)
avl = avl->lchild;
}
return avl;
}
void RotaeRR(AvlTree* &avl) {
if (!avl)
return;
else {
auto ptr = avl->lchild;
avl->lchild = ptr->rchild;
ptr->rchild = avl;
avl = ptr;
avl->height = max(Getheight(avl->lchild), Getheight(avl->rchild)) + 1;
ptr->height = max(Getheight(ptr->lchild), avl->height) + 1;
}
}
void RotaeLL(AvlTree* &avl) {
if (!avl)
return;
else {
auto ptr = avl->rchild;
avl->rchild = ptr->lchild;
ptr->lchild = avl;
avl = ptr;
avl->height = max(Getheight(avl->lchild), Getheight(avl->rchild)) + 1;
ptr->height = max(Getheight(ptr->rchild), avl->height) + 1;
}
}
void RotaeRL(AvlTree* &avl) {
if (!avl)
return;
else {
RotaeRR(avl->lchild);
RotaeLL(avl);
}
}
void RotaeLR(AvlTree* &avl) {
if (!avl)
return;
else {
RotaeLL(avl->rchild);
RotaeRR(avl);
}
}
void Insert(AvlTree* &avl, ElemType X) {
int rightheight = 0, leftheight = 0;
if (!avl) {
avl = new AvlTree;
avl->element = X;
avl->height = 0;
avl->lchild = avl->rchild = nullptr;
}
else {
if (avl->element > X) {
Insert(avl->lchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((leftheight - rightheight) > 1) {
if (avl->lchild->element > X)
RotaeRR(avl);
else
RotaeLR(avl);
}
}
else if (avl->element < X) {
Insert(avl->rchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((rightheight - leftheight) > 1) {
if (avl->rchild->element < X)
RotaeLL(avl);
else
RotaeRL(avl);
}
}
}
avl->height = max(Getheight(avl->lchild), Getheight(avl->rchild)) + 1;
}
void Delete(AvlTree* &avl, ElemType X) {
int rightheight = 0, leftheight = 0;
int rightheight_ = 0, leftheight_ = 0;
AvlTree* temp = nullptr;
if (!avl)
return;
else if (avl->element > X) {
Delete(avl->lchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((rightheight - leftheight) > 1) {
rightheight_ = Getheight(avl->rchild->rchild);
leftheight_ = Getheight(avl->rchild->lchild);
if (rightheight_ > leftheight_)
RotaeLL(avl);
else
RotaeRL(avl);
}
}
else if (avl->element < X) {
Delete(avl->rchild, X);
rightheight = Getheight(avl->rchild);
leftheight = Getheight(avl->lchild);
if ((leftheight - rightheight) > 1) {
rightheight_ = Getheight(avl->lchild->rchild);
leftheight_ = Getheight(avl->lchild->lchild);
if (rightheight_ < leftheight_)
RotaeRR(avl);
else
RotaeLR(avl);
}
}
else if (avl->element == X) {
temp = avl;
if (avl->lchild != nullptr && avl->rchild != nullptr) {
temp = FindMin(avl->rchild);
avl->element = temp->element;
Delete(avl->rchild, avl->element);
}
else if (avl->lchild == nullptr)
avl = avl->rchild;
else if (avl->rchild == nullptr)
avl = avl->lchild;
else
delete temp;
}
}
void print(AvlTree* &avl) {
if (!avl)
return;
else {
std::cout << avl->element << "\n";
print(avl->lchild);
print(avl->rchild);
}
}
int main(void)
{
std::vector<int>vec{ 1,2,3,4,5,6,7,8,9};
AvlTree* avl = nullptr;
for (const auto& x : vec) {
Insert(avl, x);
}
print(avl);
std::cout << "----------------------------------" << "\n";
std::cout << "delete a elem: 5" << "\n";
Delete(avl, 5);
print(avl);
}