AVL平衡二叉树——常用标准函数代码
AVL树仍然是一颗二叉查找树,只是在其基础上增加了**“平衡”**的要求。
由于需要对每个节点都得到平衡因子,因此需要在树的结构中加入height变量,用来记录以当前节点为根节点的子树的高度。
结构体如下:
struct node {
int v, height;
node *lchild, *rchild;
};
新建结点:
node* newNode(int v) {
node* Node = new node;
Node->v = v;
Node->height = 1;
Node->lchild = Node->rchild = NULL;
return Node;
}
获取某结点(root)的高度(height):
int getHeight(node* root) {
if(root == NULL) return 0;
return root->height;
}
计算某结点(root)的平衡因子:
int getBalanceFactor(node* root) {
//左子树高度减右子树高度
return getHeight(root->lchild) - getHeight(root->rchild);
}
更新某结点(root)的高度(height):
void updateHeight(node* root) {
//max(左孩子的height,右孩子的height) + 1
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
查找操作
查找AVL树中数据域为x的结点:
//首次传入的root为根节点指针,x为欲查找的元素值
void search(node* root, int x) {
if(root == NULL) {
printf("查找失败\n");
return;
}
if(x == root->data) {
printf("%d查找成功\n", root->data);
} else if (x < root->data) { //如果x比当前节点小
search(root->lchild, x); //递归左子树查找
} else if (x >= root->data) { //如果x比当前结点大
search(root->rchild, x); //递归右子树查找
}
}
平衡调整
左旋
void L(node* &root) {
//root指向结点A,temp指向结点B
node* temp = root->rchild;
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root); //更新A结点高度
updateHeight(temp); //更新B结点高度
root = temp;
}
右旋
void R(node* &root) {
//root指向结点B,temp指向结点A
node* temp = root->lchild;
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root); //更新B结点高度
updateHeight(temp); //更新A结点高度
root = temp;
}
AVL树插入情况汇总(BF表示平衡因子)
树型 | 判定条件 | 调整方法 |
---|---|---|
LL | BF(root) = 2, BF(root->lchild) = 1 | 对root进行右旋 |
LR | BF(root) = 2, BF(root->lchild) = -1 | 先对root->lchild进行左旋,再对root进行右旋 |
RR | BF(root) = -2, BF(root->lchild) = -1 | 对root进行左旋 |
RL | BF(root) = -2, BF(root->lchild) = 1 | 先对root->rchild进行右旋,再对root进行左旋 |
插入操作(难点)
AVL树的插入代码是在二叉查找树的插入代码的基础上增加平衡操作,因此需要在每个insert函数之后更新当前子树的高度,并在这之后根据树型是LL型、LR型、RR型、RL型之一来进行平衡操作。
//向AVL树插入权值为v的结点
void insert(node* &root, int v) {
if(root == NULL) {
root = newNode(v);
return;
}
if(v < root->v) { //v比根节点的权值小
insert(root->lchild, v); //往左子树插入
updateHeight(root); //更新树高
if(getBalanceFactor(root) == 2) { //平衡被破坏,需要调平
if(getBalanceFactor(root->lchild) == 1) { //LL型
R(root);
} else if(getBalanceFactor(root->lchild) == -1) { //LR型
L(root->lchild);
R(root);
}
}
} else { //v比根节点的权值大
insert(root->rchild, v); //往右子树插入
updateHeight(root); //更新树高
if(getBalanceFactor(root) == -2) { //平衡被破坏,需要调平
if(getBalanceFactor(root->rchild) == -1) { //RR型
L(root);
} else if(getBalanceFactor(root->rchild) == 1) { //RL型
R(root->rchild);
L(root);
}
}
}
}
AVL树的建立
有了上面的基本操作,AVL树的建立就变得非常简单了,只需要依次插入n个结点即可。
node* Create(int data[], int n) {
node* root = NULL; //新建空的根节点
for(int i = 0; i < n; i++) {
insert(root, data[i])
}
return root; //返回根结点
}
一起加油!