您的位置:首页 > 其它

AVL树

2015-08-19 09:36 225 查看
AVL树的节点声明:
typedef int ElementType;
#ifndef _AvlTree_H

struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;

AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType X,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType X,AvlTree T);
AvlTree Delete(ElementType X,AvlTree T);
ElementType Retrieve(Position P);

#endif

struct AvlNode
{
ElementType Element;
AvlTree Left;
AvlTree Right;
int Height;
};
下面只是写出了Insert函数以及它调用的函数的程序:
static int Height(Position P)
{
if(P==NULL)
return -1;
else
return P->Height;
}

static Position SingleRotateWithLeft(Position K2)
{
Position K1;
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;
}

static Position SingleRotateWithRight(Position K2)
{
Position K1;
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;
}
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 Insert(ElementType X,AvlTree T)
{
if(T==NULL)
{
T=malloc(sizeof(struct AvlNode));
if(T==NULL)
{
printf("Out of space !\n");
}

p->Element=X;
p->Left=NULL; p->Right=NULL;
p->Height=0;
}
else
{
if(X < T->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)==2)
{
if(X > T->Right->Element)
T=SingleRotateWithRight(T);
else
T=DoubleRotateWithRight(T);
}
}
}

T->Height=Max(Height(T->Left),Height(T->Right))+1;
return T;
}
在上面的Insert程序中,if(X < T->Element) 和 else if(X > T->Element)的内容是我没有写出来的,也就是几乎整个程序都没写出来。这个函数是需要谨记的!!!

仔细看这个程序的话,就会发现不是表面上看上去的那么简单!
递归调用Insert函数,接下来如果调整树。最先调整的是,距离插入节点到根的路径上,最先出现不平衡的那个子树。然后检验往上的路径中的子树是否是平衡的。

以上是书上的一个递归Insert程序。
下面是我自己写的一个非递归Insert程序:
AvlTree Insert(ElementType X,AvlTree T)
{
Position q=malloc(sizeof(struct AvlNode));
if(q==NULL)
{
printf("malloc space fail !\n");
return T;
}
q->Element=X;
q->Left=NULL; q->Right=NULL;
q->Height=0;

if(T==NULL)
return q;
if(Find(X,T))
return T;

Position p=T;
while(p!=NULL)
{
if(X < p->Element )
{
p->Height=0;
Push(p,s);
p=p->Left;
}
else if(X > p->Element )
{
p->Height=1;
Push(p,s);
p=p->Right;
}
}

p=TopAndPop(s);
int i=2, first, second=p->Height;
if(p->Height==0)
{
p->Left=q;
p->Height=1;
}
else
p->Right=q;

Position tmp;
while(!IsEmpty(s))
{
p=TopAndPop(s);
first=p->Height;
p->Height=i;

if(first==0)
{
if(Height(p->Left)-Height(p->Right)==2)
{
if(second==0)
tmp=SingleRotateWithLeft(p);
else
tmp=DoubleRotateWithLeft(p);
if(IsEmpty(s))
{
p=tmp;
}
else
{
p=Top(Stack(s));
if(p->Height==0)
p->Left=tmp;
else
p->Right=tmp;
}
}
}
else
{
if(Height(p->Right)-Height(p->Left)==2)
{
if(second==1)
tmp=SingleRotateWithRight(p);
else
tmp=DoubleRotateWithRight(p);
if(IsEmpty(s))
{
p=tmp;
}
else
{
p=Top(Stack(s));
if(p->Height==0)
p->Left=tmp;
else
p->Right=tmp;
}
}
}
second=first;
i++;
}

return p;
}
这个非递归程序的思想是这样的:
创建一个Position节点q,将Insert函数参数中的X放进去。
先判断函数的参数T是否为NULL,若是,那就返回q。

查找AVL树T中是否有元素X,若有,返回T;

第18行到33行,查找元素X的位置。从根到元素位置的路径上经过的每个节点p(包括根节点,但不包括元素X所在的节点):如果元素在它左边,这个节点的p->Height=0;如果元素在它右边,这个节点的p->Height=1, p入栈。

第35到43行,将元素X插入到正确位置,它的父节点为p,且p->Height=1。

从45行到98行,将栈s中的指针依次出栈。用i表示出栈的对应节点p的Height的值,first=0表示元素X在p的左子树上,first=1表示元素X在p的右子树上。second=0表示元素X在p的儿子的左子树上,second=1表示元素X在p的儿子的右子树上。 对于出栈的每个节点p,检查是否平衡。如果不平衡,根据first和second调用相应的单旋转或双旋转使子树p平衡。并且,根据节点p的父亲的Height值,使平衡后的子树p重新成为它父亲的对应儿子( p的父亲的Height=0,那么p在平衡前是左儿子,平衡后也应该成为左儿子)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: