AVL树是一种带有平衡性质的二叉查找树,一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1).它保证树的深度是O(logN)。我们知道,二叉查找树的平均深度为O(logN),但是,如果你顺序插入1,2,3,4,5,6……,它会产生一颗高度为O(N)的树。而AVL树可以避免这种情况,因为它有平衡的性质,当任一节点的左子树与右子树的高度差达到2时,可以自动调节树的结构,从而使得树重新平衡。
假设a原先是一颗平衡树,但插入一个点后,它的两棵子树的高度差达到2,则a此时不再平衡,这种不平衡性可能来自下面四种情况
1.对a的左儿子的左子树进行一次插入
2.对a的左儿子的右子树进行一次插入、
3.对a的右儿子的左子树进行一次插入
4.对a的右儿子的右子树进行一次插入
对上面4种情况引起的a的不平衡,可以利用旋转来解决
其中,1,4可以利用单旋转解决,2,3则需要利用双旋转解决
c语言实现如下:
/**
* AVL树:具有平衡性的二叉查找树
* 除具有二叉查找树的性质外:
* 1.每个节点的左子树和右子树的高度最多差1
*/
#ifndef __AVLTREE_H__
#define __AVLTREE_H__
typedef int ElementType;
struct AvlNode;
typedef struct AvlNode* AvlNodePtr;
typedef AvlNodePtr Position,AvlTree;
struct AvlNode{
ElementType elem;
int height;
AvlNodePtr left;
AvlNodePtr right;
};
int Height(Position p);
void InitAvlTree(AvlTree* T);
AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType x,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
Position Insert(ElementType x,AvlTree T);
Position Delete(ElementType x,AvlTree T);
void PreOrderPrintAvlTree(AvlTree T); //先序遍历
void InOrderPrintAvlTree(AvlTree T); //中序遍历
void PostOrderPrintAvlTree(AvlTree T); //后序遍历
#endif //AvlTree.h
#include "AvlTree.h"
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
//#define max((a),(b)) (a)>(b)?(a):(b) //define预处理器非常容易出问题
ElementType max(ElementType a,ElementType b)
{
return a>b?a:b;
}
/*
struct AvlNode{
ElementType elem;
int height;
AvlNodePtr left;
AvlNodePtr right;
};*/
int Height(Position p)
{
if(p==NULL)
return -1;
else
return p->height;
}
void InitAvlTree(AvlTree* T)
{
*T=NULL;
}
//不平衡来源:k2左儿子的左子树
static Position SingleRotateWithLeft(Position k2)
{
Position k1=k2->left;
k2->left=k1->right;
k1->right=k2;
k2->height=max(Height(k2->left),Height(k2->right))+1;
k1->height=max(Height(k1->left),k2->height)+1;
return k1; //new root
}
//不平衡来源:k2右儿子的右子树
static Position SingleRotateWithRight(Position k2)
{
Position k1=k2->right;
k2->right=k1->left;
k1->left=k2;
k2->height=max(Height(k2->left),Height(k2->right))+1;
k1->height=max(k2->height,Height(k1->right))+1;
return k1;
}
//不平衡来源:k2的左儿子的右子树
static Position DoubleRotateWithLeft(Position k3)
{
k3->left=SingleRotateWithRight(k3->left);
return SingleRotateWithLeft(k3);
}
static Position DoubleRotateWithRight(Position k3)
{
k3->right=SingleRotateWithLeft(k3->right);
return SingleRotateWithRight(k3);
}
AvlTree MakeEmpty(AvlTree T)
{
if(T){
MakeEmpty(T->left);
MakeEmpty(T->right);
free(T);
}
return NULL;
}
/*
Position Find(ElementType x,AvlTree T)
{
if(T==NULL)
return T;
else if(x<T->elem)
return Find(x,T->left);
else if(x>T->elem)
return Find(x,T->right);
else
return T;
}*/
Position Find(ElementType x,AvlTree T)
{
Position p=T;
while(p!=NULL && p->elem!=x){
if(x<p->elem)
p=p->left;
else
p=p->right;
}
return p;
}
Position FindMin(AvlTree T)
{
Position p=T;
if(p!=NULL){
while(p->left!=NULL)
p=p->left;
}
return p;
}
Position FindMax(AvlTree T)
{
Position p=T;
if(p!=NULL){
while(p->right!=NULL)
p=p->right;
}
return p;
}
Position Insert(ElementType x,AvlTree T)
{
if(T==NULL){
T=(AvlTree)malloc(sizeof(struct AvlNode));
if(!T){
Error("malloc error:out of space\n");
}
else{
T->elem=x;
T->left=T->right=NULL;
T->height=0;
}
//return T;
}
else if(x<T->elem){
T->left=Insert(x,T->left);
if(Height(T->left)-Height(T->right)==2){
if(x<T->left->elem)
T=SingleRotateWithLeft(T);
else
T=DoubleRotateWithLeft(T);
}
}
else if(x>T->elem){
T->right=Insert(x,T->right);
if(Height(T->right)-Height(T->left)==2){
if(x>T->right->elem)
T=SingleRotateWithRight(T);
else
T=DoubleRotateWithRight(T);
}
}
// Else x is in the tree already; we'll do nothing
T->height=max(Height(T->left),Height(T->right))+1;
return T;
}
//查找元素x的父亲节点,元素x不存在或者T为空树或只有一个根节点,则返回NULL
static Position Parent(ElementType x,AvlTree T)
{
Position parent=NULL;
Position p=T;
while(p!=NULL && p->elem!=x){
if(x<p->elem){
parent=p;
p=p->left;
}
else{
parent=p;
p=p->right;
}
}
if(p==NULL) //不存在元素x
parent=NULL;
return parent;
}
Position Delete(ElementType x,AvlTree T)
{
if(T==NULL)
return NULL;
if(x<T->elem)
T->left=Delete(x,T->left);
else if(x>T->elem)
T->right=Delete(x,T->right);
else if(T->left!=NULL && T->right!=NULL){ //有两个儿子
Position TmpCell=FindMin(T->right); //查找右子树最小节点
T->elem=TmpCell->elem;
T->right=Delete(T->elem,T->right);
}
else if(T->left!=NULL){ //只有左儿子
Position TmpCell=T;
T=T->left;
free(TmpCell);
}
else{ //只有右儿子或没有子节点
Position TmpCell=T;
T=T->right;
free(TmpCell);
}
if(T!=NULL){
if(Height(T->left)-Height(T->right)>=2){ //失去平衡
if(Height(T->left->left)>=Height(T->left->right))
T=SingleRotateWithLeft(T);
else
T=DoubleRotateWithLeft(T);
}
else if(Height(T->right)-Height(T->left)>=2){
if(Height(T->right->right)>=Height(T->right->left))
T=SingleRotateWithRight(T);
else
T=DoubleRotateWithRight(T);
}
T->height=max(Height(T->left),Height(T->right))+1;
}
return T;
}
//先序遍历
void PreOrderPrintAvlTree(AvlTree T)
{
if(T!=NULL){
printf("%d \t",T->elem);
PreOrderPrintAvlTree(T->left);
PreOrderPrintAvlTree(T->right);
}
}
//中序遍历
void InOrderPrintAvlTree(AvlTree T)
{
if(T!=NULL){
InOrderPrintAvlTree(T->left);
printf("%d \t",T->elem);
InOrderPrintAvlTree(T->right);
}
}
//后序遍历
void PostOrderPrintAvlTree(AvlTree T)
{
if(T!=NULL){
PostOrderPrintAvlTree(T->left);
PostOrderPrintAvlTree(T->right);
printf("%d \t",T->elem);
}
}