Root of AVL Tree

本文介绍了AVL树的概念,它是一种自我平衡的二叉搜索树,确保任意节点的两个子树高度最多相差1。当不平衡发生时,通过LL、RR、LR和RL四种旋转方式进行调整。给定一系列插入操作,我们需要找出最终AVL树的根节点。代码实现了插入操作并进行了相应的旋转以保持平衡,最后输出AVL树的根节点值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

Sample Input 2:

7
88 70 61 96 120 90 65

Sample Output 2:

88

解题思路:

平衡二叉树的调整可以分为四种情况:
LL旋转(左单旋)、RR旋转(右单旋)、LR旋转、RL旋转,分别指插入的结点在不平衡结点的左子树的左子树,右子树的右子树,左子树的右子树, 右子树的左子树,这里的不平衡结点指的是该结点的左右子树高度相差大于1。如下四张图,做相对应的旋转。
LL旋转

LR旋转
旋转
图片来源:浙大数据结构mooc

算法描述:(见图)

LL旋转:先将A的左子树保存下来,设为B(或其他),让A的左子树等于B的右子树,B的右子树变为A,更新高度,此时B就是新的根结点。
RR旋转:类似。
LR旋转:可以转换成,先对BC做RR旋转,然后对AC做LL旋转,最后返回C,成为新的根结点。
RL旋转:类似。

代码:

#include <iostream>

using namespace std;

int Max(int a, int b);

using AVLTree=class AVLNode*;
class AVLNode {
public:
	int Data;  //结点数据
	AVLTree Left;  //左结点
	AVLTree Right;  //右结点
	int Height;   //树高

    AVLNode() {   //无参构造函数
        Left = nullptr;
        Right = nullptr;
        Height = 1;
    }

    int GetHeight() {
        if (!Left && !Right) return 1;  //如果是叶子节点就返回1
        if (!Left && Right) return Right->Height+1;   //左空又不空
        if (Left && !Right) return Left->Height+1;   //右空左不空
        if (Left && Right) return Max(Left->Height, Right->Height)+1;
    }
    int D_Value() {
        if (!Left && !Right) return 0;  //如果是叶子节点就返回1
        if (!Left && Right) return -(Right->Height);   //左空又不空
        if (Left && !Right) return Left->Height;   //右空左不空
        if(Left && Right) return Left->Height - Right->Height;
    }
};

AVLTree LL_Rotation(AVLTree A);
AVLTree RR_Rotation(AVLTree A);
AVLTree LR_Rotation(AVLTree A);
AVLTree RL_Rotation(AVLTree A);
AVLTree Insert(AVLTree T, int X);

int main() {
    int N;  //结点数
    int X;
    AVLTree T = nullptr;

    cin >> N;
    for (int i = 0; i < N; i++) {   //建树
        cin >> X;
        T = Insert(T, X);
    }
    cout << T->Data;  //输出结果

	return 0;
}

int Max(int a, int b)
{
    return a > b ? a : b;
}

AVLTree LL_Rotation(AVLTree A)
{ /* 注意:A必须有一个左子结点B */

    AVLTree B = A->Left;   //保存A的左子树
    A->Left = B->Right;    //A的左子树子树B的右子树x
    B->Right = A;    //让A变成B的右子树
    A->Height = A->GetHeight();
    B->Height = B->GetHeight();

    return B;
}

AVLTree RR_Rotation(AVLTree A)
{ /* 注意:A必须有一个右子结点B */

    AVLTree B = A->Right;  
    A->Right = B->Left;    
    B->Left = A;    
    A->Height = A->GetHeight();
    B->Height = B->GetHeight();

    return B;
}

AVLTree LR_Rotation(AVLTree A)
{ /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */
  /* 将A、B与C做两次单旋,返回新的根结点C */

    /* 将B与C做右单旋,C被返回 */
    A->Left = RR_Rotation(A->Left);
    /* 将A与C做左单旋,C被返回 */
    return LL_Rotation(A);
}

AVLTree RL_Rotation(AVLTree A)
{ /* 注意:A必须有一个右子结点B,且B必须有一个左子结点C */
  /* 将A、B与C做两次单旋,返回新的根结点C */

    /* 将B与C做左单旋,C被返回 */
    A->Right = LL_Rotation(A->Right);
    /* 将A与C做右单旋,C被返回 */
    return RR_Rotation(A);
}

AVLTree Insert(AVLTree T, int X)
{ /* 将X插入AVL树T中,并且返回调整后的AVL树 */
    if (!T) { /* 若插入空树,则新建包含一个结点的树 */
        T = new AVLNode;
        T->Data = X;
    } /* if (插入空树) 结束 */

    else if (X < T->Data) {
        /* 插入T的左子树 */
        T->Left = Insert(T->Left, X);
        /* 如果需要左旋 */
        if (T->D_Value() == 2)
            if (X < T->Left->Data)
                T = LL_Rotation(T);      /* 左单旋 */
            else
                T = LR_Rotation(T); /* 左-右双旋 */
    } /* else if (插入左子树) 结束 */

    else if (X > T->Data) {
        /* 插入T的右子树 */
        T->Right = Insert(T->Right, X);
        /* 如果需要右旋 */
        if (T->D_Value() == -2)
            if (X > T->Right->Data)
                T = RR_Rotation(T);     /* 右单旋 */
            else
                T = RL_Rotation(T); /* 右-左双旋 */
    } /* else if (插入右子树) 结束 */

    /* else X == T->Data,无须插入 */

    /* 别忘了更新树高 */
    T->Height = T->GetHeight();

    return T;
}

运行结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

积木41

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值