AVL树是一种自平衡(Self-balancing)二叉查找树(Binary Search Tree),要求任何一个节点的左子树和右子树的高度之差不能超过1。
AVL树的插入操作首先会按照普通二叉查找树的插入操作进行,不同的是在成功插入一个节点后会向上进行回溯,判断路径中的每一个节点左子树和右子树高度之差,如果相差大于1,则进行旋转操作使得树重新达到平衡状态,旋转的本质其实是为当前不平衡的子树选择一个新的根节点,以降低两侧的高度差。
这里以root表示不平衡节点(左右子树高度差大于1),旋转操作可分为以下四种:
- 右旋转:当加入的节点在root的左子节点的左子树中(LL),以root为轴进行一次右旋转。
- 左旋转:当加入的节点在root的右子节点的右子树中(RR),以root为轴进行一次左旋转。
- 左右旋转:当加入的节点在root的左子节点的右子树中(LR),先以root的左子节点为轴进行一次左旋转,再以root为轴进行一次右旋转。
- 右左旋转:当加入的节点在root的右子节点的左子树中(RL),先以root的右子节点为轴进行一次右旋转,再以root为轴进行一次左旋转。
代码如下:
#include <cstdio>
#include <cstdlib>
#define max(x, y) (((x) > (y)) ? (x) : (y))
typedef struct tnode
{
int val;
struct tnode * left;
struct tnode * right;
} node;
//LL:右旋转
node * rotate_right(node * root) {
node * lnode = root->left;
root->left = lnode->right;
lnode->right = root;
return lnode;
}
//RR:左旋转
node * rotate_left(node * root) {
node * rnode = root->right;
root->right = rnode->left;
rnode->left = root;
return rnode;
}
//LR:先左旋转,再右旋转
node * rotate_left_right(node * root) {
root->left = rotate_left(root->left);
return rotate_right(root);
}
//RL:先右旋转,再左旋转
node * rotate_right_left(node * root) {
root->right = rotate_right(root->right);
return rotate_left(root);
}
//递归求得以root为根节点的树的高度
int get_height(node * root) {
if (root == NULL) return 0;
return max(get_height(root->left), get_height(root->right)) + 1;
}
//在以root为根节点的树中插入值为val的节点
node * insert(node * root, int val) {
if (root == NULL) {
root = (node *) malloc(sizeof(node));
root->val = val;
root->left = NULL;
root->right = NULL;
} else if (val < root->val) {
root->left = insert(root->left, val);
if (get_height(root->left) - get_height(root->right) == 2) {
if (val < root->left->val) root = rotate_right(root);
else root = rotate_left_right(root);
}
} else {
root->right = insert(root->right, val);
if (get_height(root->right) - get_height(root->left) == 2) {
if (val > root->right->val) root = rotate_left(root);
else root = rotate_right_left(root);
}
}
return root;
}
int main(void) {
int n, val;
node * root = NULL;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &val);
root = insert(root, val);
}
return 0;
}