04-树5 Root of AVL Tree (25分)

Root of AVL Tree

知识储备
  1. 树结构构建

    typedef struct TreeNode *Position;
    struct TreeNode
    {
        int value;
        Position left;
        Position right;
    };
    
  2. AVL树四种调整方式

    • LLrotation
    Position LLrotation(Position T)
    {
        Position t;
        t = T->left;
        T->left = t->right;
        t->right = T;
        return t;
    }
    
    • LRrotation
    Position LRrotation(Position T)
    {
        Position t = T->left->right;
        T->left->right = t->left;
        t->left = T->left;
        T->left = t->right;
        t->right = T;
        return t;
    }
    
    • RRrotation
    Position RRrotation(Position T)
    {
        Position t;
        t = T->right;
        T->right = t->left;
        t->left = T;
        return t;
    }
    
    • RLrotaion
    Position RLrotation(Position T)
    {
        Position t = T->right->left;
        T->right->left = t->right;
        t->right = T->right;
        T->right = t->left;
        t->left = T;
        return t;
    }
    

    这里挑选RLrotation进行讲解:

    由于节点 t t t导致了 T T T节点的不平衡,因此需要调整 T T T, A A A,和 t t t三个节点的位置。因此要将 t t t作为新的根节点,t的左子树变为 T T T t t t的右子树变为 A A A。必须还要注意重新链接 t t t原来的左子树和右子树,对应放到 T T T的右子树上和 A A A的左子树上。

    这四种调整方式推荐通过画图去理解,参考浙大mooc中的讲解。

程序理解
  1. insert 函数

    Position insert(Position T, int i)
    {
        if(!T)
            return NewNode(i);
        if(i > T->value)
        {
            T->right = insert(T->right, i);
            if(GetTreeHeight(T->right) - GetTreeHeight(T->left) == 2)
            {
                if(i > T->right->value)
                    T = RRrotation(T);
                else if(i < T->right->value)
                    T = RLrotation(T);
            }
        }
        else if(i < T->value)
        {
            T->left = insert(T->left, i);
            if(GetTreeHeight(T->left) - GetTreeHeight(T->right) == 2)
            {
                if(i > T->left->value)
                    T = LRrotation(T);
                else
                    T = LLrotation(T);
            }
        }
        return T;
    }
    

    insert 函数实际上是一个按顺序插入节点,并递归从下往上扫描树检查是否有不平衡的节点的一个函数。因此在insert 函数内部再次调用insert函数,即插入节点时,就要对该节点用GetTreeHeight进行检查,是否存在不平衡的情况。如果有,直接进入该节点的左子树/右子树判断应该使用哪一种旋转方式。所以insert操作相当于递归到最深处插入节点,再逐次返回并调整的一个函数。

  2. GetTreeHeight 函数

    int GetTreeHeight(Position T)
    {
        int H, HL, HR;
        if(!T) return 0;
        else
        {
            HL = GetTreeHeight(T->left);
            HR = GetTreeHeight(T->right);
            H = HL > HR ? HL : HR;
            return H + 1;
        }
    }
    

    此处利用递归调用函数。本来作者想在树结构中加一个height来记录平衡状态。然而在insert返回时比较难操作,要考虑太多的情况,因此还是在每次判断的时候调用测试树高的函数。如果在正规的比赛中碰到应该还是要在结构体中增加height记录,因为在计算规模较大的树时可能会超时。

附上源代码

#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode *Position;
struct TreeNode
{
    int value;
    Position left;
    Position right;
};
Position NewNode(int i);
Position MakeTree(int N);
Position insert(Position T, int n);
Position RRrotation(Position T);
int GetTreeHeight(Position T);
Position LLrotation(Position T);
Position LRrotation(Position T);
Position RLrotation(Position T);
Position RRrotation(Position T);
int main()
{
    int N;
    scanf("%d", &N);
    Position tree = MakeTree(N);
    printf("%d", tree->value);
    return 0;
}
Position NewNode(int i)
{
    Position t = (Position)malloc(sizeof(struct TreeNode));
    t->value = i;
    t->left = t->right = NULL;
    return t;
}
Position MakeTree(int N)
{
    if(N == 0) return NULL;
    int tmp;
    scanf("%d", &tmp);
    Position t = NewNode(tmp);
    for(int i = 1; i < N; i++)
    {
        scanf("%d", &tmp);
        t = insert(t, tmp);
    }
    return t;
}
int GetTreeHeight(Position T)
{
    int H, HL, HR;
    if(!T) return 0;
    else
    {
        HL = GetTreeHeight(T->left);
        HR = GetTreeHeight(T->right);
        H = HL > HR ? HL : HR;
        return H + 1;
    }

}
Position insert(Position T, int i)
{
    if(!T)
        return NewNode(i);
    if(i > T->value)
    {
        T->right = insert(T->right, i);
        if(GetTreeHeight(T->right) - GetTreeHeight(T->left) == 2)
        {
            if(i > T->right->value)
                T = RRrotation(T);
            else if(i < T->right->value)
                T = RLrotation(T);
        }
    }
    else if(i < T->value)
    {
        T->left = insert(T->left, i);
        if(GetTreeHeight(T->left) - GetTreeHeight(T->right) == 2)
        {
            if(i > T->left->value)
                T = LRrotation(T);
            else
                T = LLrotation(T);
        }
    }
    return T;
}

Position LLrotation(Position T)
{
    Position t;
    t = T->left;
    T->left = t->right;
    t->right = T;
    return t;
}

Position LRrotation(Position T)
{
    Position t = T->left->right;
    T->left->right = t->left;
    t->left = T->left;
    T->left = t->right;
    t->right = T;
    return t;
}
Position RRrotation(Position T)
{
    Position t;
    t = T->right;
    T->right = t->left;
    t->left = T;
    return t;
}
Position RLrotation(Position T)
{
    Position t = T->right->left;
    T->right->left = t->right;
    t->right = T->right;
    T->right = t->left;
    t->left = T;
    return t;
}

= T->right;
T->right = t->left;
t->left = T;
return t;
}
Position RLrotation(Position T)
{
Position t = T->right->left;
T->right->left = t->right;
t->right = T->right;
T->right = t->left;
t->left = T;
return t;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值