概念:左右子树的高度差不能超过 1 的 Binary Search Tree, 即 AVL Tree。
1. 基本概念
AVL Tree是自平衡的Binary Search Tree;- 树的节点都包含一个
balance factor,值为:-1、0、1; balance factor是左右子树的高度差;
1.1 树的节点的定义
struct avl_node {
int key;
int height;
struct avl_node *lchild, *rchild;
};
2. AVL Tree 操作
2.1 Left Rotate
-
操作步骤
- 如果 y 有左子树,则将 x 的右子树指向 y 的左子树;
- 如果 x 的父节点 p 为
NULL,则 y 变成根节点; - 否则 x 是父节点 p 的左子树,则将 y 变成 p 的左子树;
- 否则将 y 变成 p 的右子树;
- 然后将 x 变成 y 左子树;
-
代码实现
struct avl_node *AVL_LeftRotate(struct avl_node *x)
{
struct avl_node *y = x->rchild;
struct avl_node *t = y->lchild;
y->lchild = x;
x->rchild = t;
x->height = MAX(NodeHeight(x->lchild), NodeHeight(x->rchild)) + 1;
y->height = MAX(NodeHeight(y->lchild), NodeHeight(y->rchild)) + 1;
return y;
}
2.1 Right Rotate
-
操作步骤
- 如果 x 有右子树,则将 y 的左子树指向 x 的右子树;
- 如果 y 的父节点 p 为
NULL,则 x 变成根节点; - 否则 y 是父节点 p 的右子树,则将 x 变成 p 的右子树;
- 否则将 x 变成 p 的左子树;
- 然后将 y 变成 x 的右子树;
-
代码实现
struct avl_node *AVL_RightRotate(struct avl_node *y)
{
struct avl_node *x = y->lchild;
struct avl_node *t = x->rchild;
x->rchild = y;
y->lchild = t;
y->height = MAX(NodeHeight(y->lchild), NodeHeight(y->rchild)) + 1;
x->height = MAX(NodeHeight(x->lchild), NodeHeight(x->rchild)) + 1;
return x;
}
2.2 AVL_Insert 插入
-
操作步骤
- 先将 key 插入到 tree 中
- 更新树中各个节点的 height (balance factor)
- 进行自平衡操作:左旋、右旋、左右旋、右左旋
- 如果
balanceFactor > 1, 表示左子树的高度大于右子树的高度。- 如果
key < leftChildKey,则进行右旋;否则进行left-right rotate
- 如果
- 如果
balanceFactor < -1, 表示右子树的高度大于左子树的高度。- 如果
key > rightChildKey,则进行左旋;否则进行right-left rotate
- 如果
- 如果
-
代码实现
struct avl_node *AVL_Insert(struct avl_node *root, int key)
{
if (root == NULL) /* empty tree */
return AVL_NewNode(key);
if (key < root->key)
root->lchild = AVL_Insert(root->lchild, key);
else if (key > root->key)
root->rchild = AVL_Insert(root->rchild, key);
else
return root;
root->height = 1 + MAX(NodeHeight(root->lchild), NodeHeight(root->rchild));
int balance = getBalance(root);
if (balance > 1 && key < root->lchild->key)
return AVL_RightRotate(root);
if (balance > 1 && key > root->lchild->key) {
root->left = AVL_LeftRotate(root->lchild);
return AVL_RightRotate(root);
}
if (balance < -1 && key > root->rchild->key)
return AVL_LeftRotate(root);
if (balance < -1 && key < root->rchild->key) {
root->right = AVL_RightRotate(root->rchild);
return AVL_LeftRotate(root);
}
return root;
}
2.3 AVL_Delete 删除
- 操作步骤
- 通过递归找到要删除的节点;
- 然后有以下三种情况:
nodeToBeDeleted是叶子节点,直接删除即可;nodeToBeDeleted有一个子节点,用子节点的值替换掉nodeToBeDeleted的值,然后移除子节点;nodeToBeDeleted有两个子节点,找到其右子树的最小值的节点w,然后用w的值替换掉nodeToBeDeleted的值,最后移除掉w;
- 更新所有节点的
balanceFactor; - 在利用旋转,保持树的平衡性(如果有任何一个节点的
balanceFactor不等于 -1、0 或 1:- 如果当前节点
balanceFactor > 1- 如果当前节点的左子树的
balanceFactor >= 0,对当前节点做 right rotation; - 否则对当前节点做 left-right-rotation;
- 如果当前节点的左子树的
- 如果当前节点
balanceFactor < -1- 如果当前节点的右子树的
balanceFactor <= 0,对当前节点做 left rotation; - 否则对当前节点做 right-left-rotation;
- 如果当前节点的右子树的
- 如果当前节点
- 代码实现
struct avl_node *AVL_Delete(struct avl_node *root, int key)
{
if (root == NULL)
return root;
if (key < root->key)
root->lchild = AVL_Delete(root->lchild, key);
else if (key > root->key)
root->rchild = AVL_Delete(root->rchild, key);
else {
/* 此时,root 就是要删除的节点 */
if ((root->lchild == NULL) || (root->rchild == NULL)) {
struct avl_node *temp = root->lchild ? root->lchild : root->rchild;
if (temp == NULL) {
temp = root;
root = NULL;
} else
*root = *temp;
free(temp);
} else {
struct avl_node *temp = MinValueNode(root->rchild);
root->key = temp->key;
root->rchild = AVL_Delete(root->rchild, temp->key);
}
}
/* empty tree */
if (root == NULL)
return root;
/* Update the balance factor of each node and balance tree*/
root->height = 1 + MAX(NodeHeight(root->lchild), NodeHeight(root->rchild));
int balance = getBalance(root);
if (balance > 1 && getBalance(root->lchild) >= 0)
return AVL_RightRotate(root);
if (balance > 1 && getBalance(root->lchild) < 0) {
root->lchild = AVL_LeftRotate(root->lchild);
return AVL_RightRotate(root);
}
if (balance < -1 && getBalance(root->rchild) <= 0)
return AVL_LeftRotate(root);
if (balance < -1 && getBalance(root->rchild) > 0) {
root->rchild = AVL_RightRotate(root->rchild);
return AVL_LeftRotate(root);
}
return root;
}
3. 完整代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct avl_node {
int key;
int height;
struct avl_node *lchild, *rchild;
};
int max(int a, int b) {
return (a > b) ? a : b;
}
int NodeHeight(const struct avl_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
struct avl_node *AVL_NewNode(int key)
{
struct avl_node *temp = (struct avl_node *)malloc(sizeof(struct avl_node));
if (temp == NULL) {
perror("avl new node failed");
exit(-1);
}
temp->key = key;
temp->lchild = NULL;
temp->rchild = NULL;
temp->height = 1;
return temp;
}
struct avl_node *AVL_RightRotate(struct avl_node *y)
{
struct avl_node *x = y->lchild;
struct avl_node *t = x->rchild;
x->rchild = y;
y->lchild = t;
y->height = max(NodeHeight(y->lchild), NodeHeight(y->rchild)) + 1;
x->height = max(NodeHeight(x->lchild), NodeHeight(x->rchild)) + 1;
return x;
}
struct avl_node *AVL_LeftRotate(struct avl_node *x)
{
struct avl_node *y = x->rchild;
struct avl_node *t = y->lchild;
y->lchild = x;
x->rchild = t;
x->height = max(NodeHeight(x->lchild), NodeHeight(x->rchild)) + 1;
y->height = max(NodeHeight(y->lchild), NodeHeight(y->rchild)) + 1;
return y;
}
int getBalance(struct avl_node *node)
{
if (node == NULL)
return 0;
return NodeHeight(node->lchild) - NodeHeight(node->rchild);
}
struct avl_node *MinValueNode(struct avl_node *node)
{
struct avl_node *p = node;
while (p != NULL && p->lchild != NULL)
p = p->lchild;
return p;
}
struct avl_node *AVL_Insert(struct avl_node *root, int key)
{
if (root == NULL) /* empty tree */
return AVL_NewNode(key);
if (key < root->key)
root->lchild = AVL_Insert(root->lchild, key);
else if (key > root->key)
root->rchild = AVL_Insert(root->rchild, key);
else
return root;
root->height = 1 + max(NodeHeight(root->lchild), NodeHeight(root->rchild));
int balance = getBalance(root);
if (balance > 1 && key < root->lchild->key)
return AVL_RightRotate(root);
if (balance > 1 && key > root->lchild->key) {
root->lchild = AVL_LeftRotate(root->lchild);
return AVL_RightRotate(root);
}
if (balance < -1 && key > root->rchild->key)
return AVL_LeftRotate(root);
if (balance < -1 && key < root->rchild->key) {
root->rchild = AVL_RightRotate(root->rchild);
return AVL_LeftRotate(root);
}
return root;
}
struct avl_node *AVL_Delete(struct avl_node *root, int key)
{
if (root == NULL)
return root;
if (key < root->key)
root->lchild = AVL_Delete(root->lchild, key);
else if (key > root->key)
root->rchild = AVL_Delete(root->rchild, key);
else {
/* 此时,root 就是要删除的节点 */
if ((root->lchild == NULL) || (root->rchild == NULL)) {
struct avl_node *temp = root->lchild ? root->lchild : root->rchild;
if (temp == NULL) {
temp = root;
root = NULL;
} else
*root = *temp;
free(temp);
} else {
struct avl_node *temp = MinValueNode(root->rchild);
root->key = temp->key;
root->rchild = AVL_Delete(root->rchild, temp->key);
}
}
/* empty tree */
if (root == NULL)
return root;
/* Update the balance factor of each node and balance tree*/
root->height = 1 + max(NodeHeight(root->lchild), NodeHeight(root->rchild));
int balance = getBalance(root);
if (balance > 1 && getBalance(root->lchild) >= 0)
return AVL_RightRotate(root);
if (balance > 1 && getBalance(root->lchild) < 0) {
root->lchild = AVL_LeftRotate(root->lchild);
return AVL_RightRotate(root);
}
if (balance < -1 && getBalance(root->rchild) <= 0)
return AVL_LeftRotate(root);
if (balance < -1 && getBalance(root->rchild) > 0) {
root->rchild = AVL_RightRotate(root->rchild);
return AVL_LeftRotate(root);
}
return root;
}
void printPreOrder(struct avl_node *root)
{
if (root != NULL) {
printf("%d ", root->key);
printPreOrder(root->lchild);
printPreOrder(root->rchild);
}
}
int main()
{
struct avl_node *root = NULL;
root = AVL_Insert(root, 2);
root = AVL_Insert(root, 1);
root = AVL_Insert(root, 7);
root = AVL_Insert(root, 4);
root = AVL_Insert(root, 5);
root = AVL_Insert(root, 3);
root = AVL_Insert(root, 8);
printPreOrder(root);
root = AVL_Delete(root, 3);
printf("\nAfter deletion: ");
printPreOrder(root);
printf("\n");
return 0;
}