AVL树是带有平衡条件的二叉查找树。主要的一种AVL树是这样一种树:它带有平衡条件,它的每个节点的左子树和右子树的的高度最多相差1。下面左边的树是AVL树,右边不是,因为7的左右子树的高度相差大于1。
当一个节点插入破坏了某个点的平衡。我们假设这个点是a。可能有下面有下面四种情况破坏了平衡。
1.对a的左儿子的左子树进行一次插入。
2.对a的左儿子的右子树进行一次插入。
3.对a的右儿子的左子树进行一次插入。
4.对a的右儿子的右子树进行一次插入。
情形1和4是关于a点的镜像对称,而2和3是关于a点的镜像对称。
1.单旋转
针对情形1和4。采用单旋转可以重新调整平衡。
情形1:
为使左边的树恢复平衡,我们把x上移一层,把z下移一层。重新安排k1和k2得到右边的图。相当于把k1几点往上提,这时k2变成了k1的右子树。原来的k1的右子树变成了k2的左子树。
2.双旋转
针对情形2和3,单旋转无法实现树的平衡。必须旋转两次。
上面的图在k3点经过一次左旋转(将k2往上提),得到下面的图。
上面的图在k1点经过右旋转可以得到下面的图。这就是一个AVL树了。
3 AVL树的实现
下面是AVL树的实现,需要注意的时,树的结构有一个字段is_delete来标记节点是否逻辑删除,也就是懒删除。
3.1 头文件
//
// AVLTree.h
// AVLTree
//
// Created by Wuyixin on 2017/5/28.
// Copyright © 2017年 Coding365. All rights reserved.
//
#ifndef AVLTree_h
#define AVLTree_h
#include <stdio.h>
#include <stdlib.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
typedef int ElemType;
struct AVLNODE;
typedef struct AVLNODE AvlNode;
typedef struct AVLNODE *Position;
typedef struct AVLNODE *AvlTree;
/* 置为空树 */
AvlTree make_empty(AvlTree t);
/* 查找节点 */
Position find(ElemType x,AvlTree t);
/* 查找最小节点 */
Position find_min(AvlTree t);
/* 查找最大节点 */
Position find_max(AvlTree t);
/* 插入节点 */
AvlTree insert(ElemType x,AvlTree t);
/* 删除节点--lazy删除 */
void delete_lazy(ElemType x,AvlTree t);
/* 树的遍历--中序遍历 */
void print_tree(AvlTree t);
struct AVLNODE
{
ElemType elem;
AvlTree left;
AvlTree right;
int height;
int is_delete;
};
#endif /* AVLTree_h */
3.2 实现文件
//
// AVLTree.c
// AVLTree
//
// Created by Wuyixin on 2017/5/28.
// Copyright © 2017年 Coding365. All rights reserved.
//
#include "AVLTree.h"
static int height(Position p){
if (p == NULL)
return -1;
else
return p->height;
}
/* 左旋转 */
static Position single_rotate_left(Position k2);
/* 右旋转 */
static Position single_rotate_right(Position k2);
/* 右-左旋转 */
static Position double_rotate_left(Position k3);
/* 左-右旋转 */
static Position double_rotate_right(Position k3);
AvlTree make_empty(AvlTree t){
if (t != NULL){
make_empty(t->left);
make_empty(t->right);
free(t);
}
return NULL;
}
Position find(ElemType x,AvlTree t){
if (t == NULL)
return NULL;
if (x < t->elem)
return find(x, t->left);
else if(x > t->elem)
return find(x, t->right);
else
return t;
}
Position find_min(AvlTree t){
if (t == NULL)
return NULL;
else if(t->left == NULL)
return t;
else
return find_min(t->left);
}
Position find_max(AvlTree t){
if (t == NULL)
return NULL;
else if(t->right == NULL)
return t;
else
return find_max(t->right);
}
static Position single_rotate_left(Position k2){
Position k1;
k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k1->height = MAX(height(k1->left), height(k2->right)) + 1;
k2->height = MAX(height(k2->left), height(k2->right)) + 1;
return k1;
}
static Position single_rotate_right(Position k2){
Position k1;
k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
k1->height = MAX(height(k1->left), height(k2->right)) + 1;
k2->height = MAX(height(k2->left), height(k2->right)) + 1;
return k1;
}
static Position double_rotate_left(Position k3){
/* k1与k2之间 */
k3->left = single_rotate_right(k3->left);
/* k2与k3之间*/
return single_rotate_left(k3);
}
static Position double_rotate_right(Position k3){
/* k1与k2之间 */
k3->right = single_rotate_left(k3->right);
/* k2与k3之间*/
return single_rotate_right(k3);
}
AvlTree insert(ElemType x,AvlTree t){
if (t == NULL) {
t = (AvlTree)malloc(sizeof(AvlNode));
if (t == NULL) exit(EXIT_FAILURE);
t->left = t->right = NULL;
t->elem = x;
t->is_delete = 0;
}else if(x < t->elem){
t->left = insert(x, t->left);
if (height(t->left) - height(t->right) > 1){
if (x < t->left->elem)
t = single_rotate_left(t);
else
t = double_rotate_left(t);
}
}else if(x > t->elem){
t->right = insert(x, t->right);
if (height(t->right) - height(t->left) > 1){
if (x > t->right->elem)
t = single_rotate_right(t);
else
t = double_rotate_right(t);
}
}else
/* 如果x在树中,看它是否被标记删除 */
t->is_delete = 0;
t->height = MAX(height(t->left), height(t->right)) + 1;
return t;
}
void print_tree(AvlTree t)
{
if(t != NULL && !t->is_delete){
print_tree(t->left);
printf("%d ",t->elem);
print_tree(t->right);
}
}
void delete_lazy(ElemType x,AvlTree t){
Position p = find(x, t);
if (p != NULL) p->is_delete = 1;
}
3.3 调用
//
// main.c
// AVLTree
//
// Created by Wuyixin on 2017/5/28.
// Copyright © 2017年 Coding365. All rights reserved.
//
#include <stdio.h>
#include "AVLTree.h"
int main(int argc, const char * argv[]) {
AvlTree t = NULL;
t = insert(1, t);
t = insert(2, t);
t = insert(3, t);
t = insert(4, t);
t = insert(5, t);
t = insert(6, t);
t = insert(7, t);
t = insert(8, t);
t = insert(9, t);
t = insert(10, t);
print_tree(t);
delete_lazy(5, t);
printf("\n");
print_tree(t);
return 0;
}