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

摘要:(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;
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/pp634077956/article/details/48136095
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞