AVL树是带有平衡条件的二叉查找树。这个平衡条件必须要容易保持,而且它须保证树的深度是O(log N).**一棵AVL树是其每个节点的左子树和右子树的高度最多插1的二叉查找树**
基本的数据结构:
struct AvlNode;
typedef struct AvlNode *Position ;
typedef struct AvlNode *AvlTree;
struct AvlNode
{
int Element;
AvlTree Left;
AvlTree Right;
int height;
};
static int Height(Postion P)
{
if(P==NULL)
{
return -1;
}
else
return P->Height;
}
当进行插入操作时,我们需要更新通向根节点路径上那些节点的所有平衡信息,而插入操作隐含着困难的原因在于,插入一个节点可能破坏AVL树的特性。如果发生这种情况,那么就要把性质恢复以后才认为这一步插入完成。事实上,这总可以通过对树进行简单的修正来做到,我们称其为旋转。
平衡化旋转有两类:
单旋转:
左旋的代码实现:
static Position SingleRotateWithLeft(Postion K2)
{
Position k1;
k1=k2->Left;
k2->left=k1->Right;
k1->Right=k2;
k2->Height=Max(Height(k2->Left),Height(k2->Right));
k2->Height=Max(Height(k1->Left),Height(k2->Height));
return k1;
}
右旋的代码实现:
static Position SingleRotateWithHeight(Postion K2)
{
Position k1;
k1=k2->Right;
k1->Height=k2->Left;
k2->Left=k1;
k2->Height=Max(Height(k2->Left),Height(k2->Right));
k2->Height=Max(Height(k1->Left),Height(k2->Height));
return k2;
}
双旋转
先右后左双旋转代码实现:
static Position DoubleRotateWithLeft(Position k3)
{
k3-Left=SingleRotateWithRight(k3->Left);//旋转k1和k2
return SingleWithLeft(k3)//旋转k3和k2
}
先左后右双旋转代码实现
static Position DoubleRotateWithLeft(Position k3)
{
k3->Right=SingleRotateWithLeft(k3->Right);//旋转k1和k2
return SingleWithHeight(k3)//旋转k3和k2
}
向AVL树插入节点的函数实现:
AvlTree Insert(int X,AvlTree T)
{
if(T==NULL)/*Create and return a one-node tree*/
{
T=malloc(sizeof(struct AvlNode));
if(T==NULL)
{
printf("Out of space");
}
else
{
T->Element=X;
T->Height=0;
T->Left=T->Right=NULL;
}
}
else if(X<Element)
{
T->Left=Insert(X,T->Left);
if(Height(T->Left)-Height(T->Right)==2)
{
if(X<T->Left->Element)
{
T=SingleRotateWithLeft(T);
}
else
T=DoubleRotateWithLeft(T);
}
else if(X>T->Element)
{
T->Right=Insert(X,T->Right);
if(Height(T->Right)-Height(T->Left))
{
T=SingleRotateWithRight(T);
}
else
{
T=DoubleRotateWithRight(T);
}
}
/*Else is in the tree already ,we will do nothing*/
T->Height=Max(Height(T->Left),Height(T->Right))+1;
}
}
参考资料:
1,《数据结构与算法分析c语言描述》。
2,http://www.cnblogs.com/skywang12345/p/3577360.html