✍个人博客: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
树,并输出它的根结点。
思路
平衡二叉树失衡主要分为四种情况,下面讨论的是导致失衡前最后插入的一个结点位置:
- 插入的结点在失衡结点的左孩子的左子树,直接右旋失衡结点。
- 插入的结点在失衡结点的左孩子的右子树,先对失衡结点的左孩子进行左旋,再对失衡结点右旋。
- 插入的结点在失衡结点的右孩子的右子树,直接左旋失衡结点。
- 插入的结点在失衡结点的右孩子的左子树,先对失衡结点的右孩子进行右旋,再对失衡结点左旋。
代码
#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;
}