摘要:(1)插入的基本思路;首先递归的插入,插入完成之后,逐个返回,对于返回的每一个节点都要检查,是否该次插入是使得这个节点不平衡。为了简化代码,定义一个Height()函数,用来处理该节点为NULL的情况。当该节点不平衡时,就要进行旋转。根据插入元素与该节点元素儿子的大小关系可以确定旋转类型。
(2)非递归编程有一点麻烦:基本思路还是用一个栈来保留经过的节点。
int Height(Position T)//获得高度
{
if (T==NULL)
return -1;
else
return T->Height;
}
int Max(int x,int y)//返回一个较大值
{
if (x == y)
return x;
else
return x>y?x:y;
}
Position InsertAvl(Position T,int X)//递归算法
{
if (T == NULL)
{
T = (Position)malloc(sizeof(AvlTreeRecord));
T->Element = X;
T->Height = 0;
T->Left = NULL;
T->Right = NULL;
}
else
//
{
if (X >T->Element)
{
T->Right = InsertAvl(T->Right,X);
if (Height(T->Right)-Height(T->Left) == 2){//需要调整
if (X > T->Right->Element)
T = SingleRotateRight(T);
else
T = DoubleRotateRight(T);
}
}
else if (X< T->Element)
{
T->Left = InsertAvl(T->Left,X);
if(Height(T->Left)-Height(T->Right) == 2){//需要调整
if (X < T->Left->Element)
T = SingleRotateLeft(T);
else
T = DoubleRotateLeft(T);
}
}
T->Height = Max(Height(T->Left),Height(T->Right))+1;
return T;
}
}
Position Insert_noninduction(int X,Position T)
{
int mark1,mark2;
Position Temp = T;
List L,P;
L = (List)malloc(sizeof(ListRecord));
L->mark = -1;
P = L->Next;
if (T == NULL)
{
//直接插入
T = Create(X);
return T;
}
while(1)
{
if (X > T->Element)//进入右子树
{
//链表记录
L->Next = CreateList(T);
L->Next->Previous = L;
L = L->Next;
L->mark = Rtree;
if (T->Right == NULL)
{
T->Right = Create(X);
break;
}
else
T = T->Right;
}
else //进入左子树
{
//链表记录
L->Next = CreateList(T);
L->Next->Previous = L;
L = L->Next;
L->mark = Ltree;
if (T->Left == NULL)
{
T->Left = Create(X);
break;
}
else
T = T->Left;
}
}//while
P = L;//保存最后的节点,方便确定旋转
while(L->mark!=-1)
{
//从叶子向上计算插入路径上节点的高度
L->Pointer->Height = Max(Height(L->Pointer->Left),Height(L->Pointer->Right))+1;
L = L->Previous;
}
L = P;//将L恢复到插入节点的父节点
//进行判断是否旋转以及进行节点连接
do
{
if (abs(Height(L->Pointer->Left) - Height(L->Pointer->Right)) == 2)
{
T = L->Pointer;
mark1 = L->mark;
mark2 = L->Next->mark;
switch (mark1)
{
//确定进行哪种调整
case Rtree:
if (mark2 == Rtree)
T = SingleRotateRight(T);
else
T = DoubleRotateRight(T);
break;
case Ltree:
if (mark2 == Ltree)
T = SingleRotateLeft(T);
else
T = DoubleRotateLeft(T);
break;
}
//用来确定旋转后与父节点的链接方式
if (L->Previous->mark != -1)
{
switch(L->Previous->mark)
{
case Rtree:
L->Previous->Pointer->Right = T;
break;
case Ltree:
L->Previous->Pointer->Left = T;
}
}
else
//root 是调整点,无需与父节点链接.
Temp = T;
}
L = L->Previous;
} while(L->mark != -1);
return Temp;
}