【PAT甲级 - C++题解】1066 Root of AVL Tree

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1066 Root of AVL Tree (pintia.cn)
🔑中文翻译:AVL树的根
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1066 Root of AVL Tree

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
题意

给定一个序列,让我们构建起一颗 AVL 树,并输出它的根结点。

思路

平衡二叉树失衡主要分为四种情况,下面讨论的是导致失衡前最后插入的一个结点位置:

  1. 插入的结点在失衡结点的左孩子的左子树,直接右旋失衡结点。
  2. 插入的结点在失衡结点的左孩子的右子树,先对失衡结点的左孩子进行左旋,再对失衡结点右旋
  3. 插入的结点在失衡结点的右孩子的右子树,直接左旋失衡结点。
  4. 插入的结点在失衡结点的右孩子的左子树,先对失衡结点的右孩子进行右旋,再对失衡结点左旋
代码
#include<bits/stdc++.h>
using namespace std;

const int N = 25;
int l[N], r[N], v[N], h[N], idx;
int n;

//更新当前结点的深度
void update(int u)
{
    h[u] = max(h[l[u]], h[r[u]]) + 1;
}

//右旋
void R(int& u)
{
    int p = l[u];
    l[u] = r[p], r[p] = u;
    update(u), update(p);
    u = p;
}

//左旋
void L(int& u)
{
    int p = r[u];
    r[u] = l[p], l[p] = u;
    update(u), update(p);
    u = p;
}

//获取左右结点深度之差
int get_balance(int u)
{
    return h[l[u]] - h[r[u]];
}

//插入结点
void insert(int& u, int w)
{
    if (!u)  u = ++idx, v[u] = w;
    else if (w < v[u])
    {
        insert(l[u], w);
        if (get_balance(u) == 2)
        {
            //如果插入结点在失衡结点的左孩子的左子树,则对失衡结点右旋
            if (get_balance(l[u]) == 1)   R(u);
            //如果插入结点在失衡结点的左孩子的右子树,则先对左孩子左旋,再对失衡结点右旋
            else    L(l[u]), R(u);
        }
    }
    else
    {
        insert(r[u], w);
        if (get_balance(u) == -2)
        {
            //如果插入结点在失衡结点的右孩子的右子树,则对失衡结点左旋
            if (get_balance(r[u]) == -1)   L(u);
            //如果插入结点在失衡结点的右孩子的左子树,则先对右孩子右旋,再对失衡结点左旋
            else    R(r[u]), L(u);
        }
    }

    update(u);	//更新当前结点的深度
}

int main()
{
    cin >> n;

    int root = 0;
    for (int i = 0; i < n; i++)
    {
        int w;
        cin >> w;
        insert(root, w);
    }

    cout << v[root] << endl;

    return 0;
}
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值