Problem Description
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
Solution
题意理解:给出平衡二叉树的插入顺序,输出该平衡二叉树的根结点。
- 抽象数据类型:数据域、左右子树地址、树高。
- 需要实现平衡二叉树的操作集:调整、插入。
建树函数:逐个读入逐个插入即可
插入函数:
- 如果是空结点,创建节点并返回。节点值 item、左右子树 NULL 、树高 0
- 如果结点非空,插入左右子树
- 如果 item < T->data ,插入左子树
- 如果比左子树的左结点小,则麻烦结点在左子树左边,LL 左左旋
- 如果比左子树的右结点大(else),麻烦结点在左子树右边,LR 左右旋
- 如果 item > T->data ,插入右子树
- 如果比右子树的右结点大,则麻烦结点在右子树右边, RR 右右旋
- 如果比右子树的左结点小(else),麻烦结点在右子树左边, RL 右左旋
- 如果 item < T->data ,插入左子树
- 最后记得用 max 函数更新树高
- 返回插入结点后的树
获取树高函数:
- 在结点域内有一个 height
- 如果结点为空,直接返回 0
- 如果结点非空,返回这个结点域的值 height
左左旋(右右旋):
- 规定传入的根结点是 A ,标记对应的 B ,直接指针操作即得
左右旋(右左旋):可以分解为两个单旋直接复用单旋函数即可大大简化
- 找好 A 、B、C
- 先对 B 进行单旋返回
- 再对 A 进行单旋返回
#include <stdio.h>
#include <stdlib.h>
typedef struct TNode *AVL;
struct TNode {
int data;
AVL left;
AVL right;
int height;
};
int Max(int a, int b) { return a > b ? a : b; };
int GetHeight(AVL T)
{
if (!T) return 0;
else return T->height;
}
AVL RRrotation(AVL A)
{
AVL B = A->right;
A->right = B->left;
B->left = A;
A->height = Max(GetHeight(A->left), GetHeight(A->right)) + 1;
B->height = Max(GetHeight(B->left), GetHeight(B->right)) + 1;
return B;
}
AVL LLrotation(AVL A)
{
AVL B = A->left;
A->left = B->right;
B->right = A;
A->height = Max(GetHeight(A->left), GetHeight(A->right)) + 1;
B->height = Max(GetHeight(B->left), GetHeight(B->right)) + 1;
return B;
}
AVL RLrotation(AVL A)
{
A->right = LLrotation(A->right);
return RRrotation(A);
}
AVL LRrotation(AVL A)
{
A->left = RRrotation(A->left);
return LLrotation(A);
}
AVL Insert(AVL T, int item)
{
if (!T) {
T = (AVL)malloc(sizeof(struct TNode));
T->data = item;
T->left = T->right = NULL;
T->height = 0;
} else {
if (item < T->data) {
T->left = Insert(T->left, item);
if (GetHeight(T->left) - GetHeight(T->right) == 2) {
if (item < T->left->data)
T = LLrotation(T);
else
T = LRrotation(T);
}
} else if (item > T->data) {
T->right = Insert(T->right, item);
if (GetHeight(T->right) - GetHeight(T->left) == 2) {
if (item > T->right->data)
T = RRrotation(T);
else
T = RLrotation(T);
}
}
}
T->height = Max(GetHeight(T->left), GetHeight(T->right)) + 1;
return T;
}
AVL Create(int n)
{
int item;
AVL T = NULL;
while (n--) {
scanf("%d", &item);
T = Insert(T, item);
}
return T;
}
void Free(AVL T)
{
if (T->left) Free(T->left);
if (T->right) Free(T->right);
free(T);
}
int main()
{
int n;
AVL T;
scanf("%d", &n);
T = Create(n);
printf("%d", T->data);
Free(T);
return 0;
}
Sum-up
抽象数据类型中增加了树高。
本题综合训练了平衡二叉树的操作集:
- 插入
- 更新树高
- 调整
- 单旋
- 双旋