1、AVL树概念
AVL树是带有一种平衡条件的二叉查找树,树的深度为O(logN);左右子树看起来相对平衡,一颗不平衡的树可能意味着树的操作会大于O(logN),AVL树就是能很好的保持在O(logN)的一种算法;
性质1:左右子树深度最多差1的二叉查找树;
性质2:左右子树都是平衡二叉树;
除叶子结点以外,其他结点均有两个children的树称为完全二叉树或理想平衡树,或者也可以说左右子树深度相同,但是实现的难度较大;当然也是AVL树;
2、AVL树的操作
对于普通的二叉查找树,可能会因为删除或添加的频繁操作而导致一颗树越来越不平衡;而AVL树是对这些操作之后的树进行一些修正生成的树,这些修正被称为旋转操作,一般可以分为四种情况:
情况1:插入节点位于X的左子节点的左子树--左左;
情况2:插入节点位于X的左子节点的右子树--左右;
情况3:插入节点位于X的右子节点的左子树--右左;
情况4:插入节点位于X的右子节点的右子树--右右。
情况1和情况4是镜像的,只需单旋转一次操作即可完成平衡操作;情况2和情况3是镜像的,需要双旋转两次操作才能完成平衡操作;
附几张图解释一下;
左左单旋转:在18的左结点14的左子树插入11,打破了平衡性;将18作为14的右子树,14的右子树作为18的左子树;
左右双旋转:在18的左结点的右子树插入15,打破了平衡性;将14和16做左旋转,再将16和18做右旋转;
3、AVL树代码示例
数据结构描述
struct AvlTree
{
int element;
struct AvlTree *left;
struct AvlTree *right;
int height;
};
测试代码:
#include
#include
struct AvlTree
{
int element;
struct AvlTree *left;
struct AvlTree *right;
int height;
};
int printf_tree_inorder_traversal(struct AvlTree *tree)
{
if (tree == NULL)
{
return 0;
}
if (tree->left != NULL)
{
printf_tree_inorder_traversal(tree->left);
}
printf("%d:%dh ", tree->element, tree->height);
if (tree->right != NULL)
{
printf_tree_inorder_traversal(tree->right);
}
return 0;
}
int get_tree_height(struct AvlTree *tree)
{
if (tree == NULL)
{
return -1;
}
else
{
return tree->height;
}
}
int get_max_tree_height(struct AvlTree *tree)
{
int letf_height, right_height;
letf_height = get_tree_height(tree->left);
right_height = get_tree_height(tree->right);
return (letf_height > right_height) ? letf_height : right_height;
}
struct AvlTree *make_empty(struct AvlTree *tree)
{
if (tree != NULL)
{
make_empty(tree->left);
make_empty(tree->right);
free(tree);
}
return NULL;
}
/* 0 means right, 1 means left */
static struct AvlTree *single_rotate(struct AvlTree *tree, int operate)
{
struct AvlTree *tree_tmp;
//printf("tree->element %d get in single rotate\n", tree->element);
if (operate == 0)
{
tree_tmp = tree->left;
tree->left = tree_tmp->right;
tree_tmp->right = tree;
tree_tmp->height = get_max_tree_height(tree_tmp) + 1;
tree->height = get_max_tree_height(tree) + 1;
}
else if (operate == 1)
{
tree_tmp = tree->right;
tree->right = tree_tmp->left;
tree_tmp->left = tree;
tree_tmp->height = get_max_tree_height(tree_tmp) + 1;
tree->height = get_max_tree_height(tree) + 1;
}
else
{
printf("not support this %d operate !\n", operate);
}
return tree_tmp;
}
struct AvlTree *double_rotate(struct AvlTree *tree, int operate)
{
//printf("tree->element %d get in double rotate\n", tree->element);
if (operate == 0)
{
tree->right = single_rotate(tree->right, 0);
return single_rotate(tree, 1);
}
else if (operate == 1)
{
tree->left = single_rotate(tree->left, 1);
return single_rotate(tree, 0);
}
return tree;
}
/* 0 means right, 1 means left */
struct AvlTree *insert_node(struct AvlTree *tree, int element)
{
if (tree == NULL)
{
tree = (struct AvlTree *)malloc(sizeof(struct AvlTree));
if (tree == NULL)
{
printf("malloc failed!\n");
return NULL;
}
else
{
tree->element = element;
tree->left = NULL;
tree->right = NULL;
tree->height = 0;
printf("add element : %d success\n", element);
}
}
else if (element < tree->element)
{
//printf("element %d < tree->element %d\n", element, tree->element);
tree->left = insert_node(tree->left, element);
if ((get_tree_height(tree->left) - get_tree_height(tree->right)) == 2)
{
if (tree->left->element > element)
{
tree = single_rotate(tree, 0);
}
else
{
tree = double_rotate(tree, 1);
}
}
}
else if (element > tree->element)
{
//printf("element %d > tree->element %d\n", element, tree->element);
tree->right = insert_node(tree->right, element);
if ((get_tree_height(tree->right) - get_tree_height(tree->left)) == 2)
{
if (tree->right->element < element)
{
tree = single_rotate(tree, 1);
}
else
{
tree = double_rotate(tree, 0);
}
}
}
tree->height = get_max_tree_height(tree) + 1;
printf_tree_inorder_traversal(tree);
printf("\n");
return tree;
}
struct AvlTree *find_node(struct AvlTree *tree, int element)
{
if (tree == NULL)
{
printf("can't find element %d\n", element);
return NULL;
}
else if (element < tree->element)
{
//printf("element %d < tree->element %d\n", element, tree->element);
return find_node(tree->left, element);
}
else if (element > tree->element)
{
//printf("element %d > tree->element %d\n", element, tree->element);
return find_node(tree->right, element);
}
else if (element == tree->element)
{
printf("find element : %d success\n", element);
}
return tree;
}
struct AvlTree *find_min_node(struct AvlTree *tree)
{
if (tree == NULL)
{
printf("find min node Tree is NULL!\n");
return NULL;
}
if (tree->left == NULL)
{
return tree;
}
else
{
return find_min_node(tree->left);
}
}
struct AvlTree *delete_node(struct AvlTree *tree, int element)
{
struct AvlTree *tree_tmp;
if (tree == NULL)
{
printf("Tree is NULL\n");
return NULL;
}
else if (element < tree->element)
{
//printf("element %d < tree->element %d\n", element, tree->element);
tree->left = delete_node(tree->left, element);
if ((get_tree_height(tree->left) - get_tree_height(tree->right)) == 2)
{
if (tree->left->element > element)
{
tree = single_rotate(tree, 0);
}
else
{
tree = double_rotate(tree, 1);
}
}
}
else if (element > tree->element)
{
//printf("element %d > tree->element %d\n", element, tree->element);
tree->right = delete_node(tree->right, element);
if ((get_tree_height(tree->right) - get_tree_height(tree->left)) == 2)
{
if (tree->right->element < element)
{
tree = single_rotate(tree, 1);
}
else
{
tree = double_rotate(tree, 0);
}
}
}
else
{
//two children
if (tree->right != NULL && tree->left != NULL)
{
tree_tmp = find_min_node(tree->right);
tree->element = tree_tmp->element;
tree->right = delete_node(tree->right, tree->element);
}
//one or zero children
else
{
tree_tmp = tree;
if (tree->right == NULL)
{
tree = tree->left;
}
else if (tree->left == NULL)
{
tree = tree->right;
}
free(tree_tmp);
printf("delete element %d success\n", tree_tmp->element);
}
}
if (tree)
tree->height = get_max_tree_height(tree) + 1;
return tree;
}
int main(void)
{
struct AvlTree tree;
struct AvlTree *tmp_node = NULL;
int num[10] = {30, 4, 31, 10, 18, 16, 28, 15, 12, 14};
int i;
tree.element = 5;
tree.left = NULL;
tree.right = NULL;
tmp_node = &tree;
printf("root element : %d\n", tree.element);
for (i = 0; i < 10; i++)
{
tmp_node = insert_node(tmp_node, num[i]);
printf("\n");
}
printf_tree_inorder_traversal(tmp_node);
printf("\n");
delete_node(tmp_node, 18);
printf_tree_inorder_traversal(tmp_node);
printf("\n");
return 0;
}
执行结果:
root element : 5
add element : 30 success
30:0h
5:1h 30:0h
add element : 4 success
4:0h
4:0h 5:1h 30:0h
add element : 31 success
31:0h
30:1h 31:0h
4:0h 5:2h 30:1h 31:0h
add element : 10 success
10:0h
10:0h 30:1h 31:0h
4:0h 5:2h 10:0h 30:1h 31:0h
add element : 18 success
18:0h
10:1h 18:0h
10:1h 18:0h 30:2h 31:0h
4:0h 5:1h 10:2h 18:0h 30:1h 31:0h
add element : 16 success
16:0h
16:0h 18:1h
16:0h 18:1h 30:2h 31:0h
4:0h 5:1h 10:3h 16:0h 18:1h 30:2h 31:0h
add element : 28 success
28:0h
16:0h 18:1h 28:0h
16:0h 18:1h 28:0h 30:2h 31:0h
4:0h 5:1h 10:3h 16:0h 18:1h 28:0h 30:2h 31:0h
add element : 15 success
15:0h
15:0h 16:1h
15:0h 16:1h 18:2h 28:0h
15:0h 16:1h 18:2h 28:0h 30:1h 31:0h
4:0h 5:1h 10:3h 15:0h 16:1h 18:2h 28:0h 30:1h 31:0h
add element : 12 success
12:0h
12:0h 15:1h
12:0h 15:1h 16:0h
12:0h 15:1h 16:0h 18:2h 28:0h 30:1h 31:0h
4:0h 5:1h 10:3h 12:0h 15:1h 16:0h 18:2h 28:0h 30:1h 31:0h
add element : 14 success
14:0h
12:1h 14:0h
12:1h 14:0h 15:2h 16:0h
12:1h 14:0h 15:2h 16:0h 18:3h 28:0h 30:1h 31:0h
4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 18:2h 28:0h 30:1h 31:0h
4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 18:2h 28:0h 30:1h 31:0h
delete element 28 success
4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 28:2h 30:1h 31:0h