AVL树的基本操作之插入(递归与非递归编码)(2)

来源:互联网 发布:linux home目录不见了 编辑:程序博客网 时间:2024/06/08 08:29

摘要:(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;}
0 0
原创粉丝点击