n 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
题目分析:
这道题的题意是给n个元素,让你输出其二叉平衡树的根节点数据。其实考察的就是二叉平衡树的旋转。一共有四种旋转,LL,LR,RR,RL。然后依据插入的节点是否破坏了平衡,以及破坏平衡的位置与根节点的关系进行调整。
代码如下:
#include <iostream>
#include <new>
#include <string>
using namespace std;
typedef struct AVLTreeNode* AVLTree;
struct AVLTreeNode{
int height; //记录树高
int number;
AVLTree left, right;
};
AVLTree RightRightRotation(AVLTree T); //RR旋转
AVLTree LeftLeftRotation(AVLTree T); //LL旋转
AVLTree LeftRightRotation(AVLTree T); //LR旋转
AVLTree RightLeftRotation(AVLTree T); //RL旋转
AVLTree CreateAVLTreeNode(int v); //建树
AVLTree DeleteAVLTreeNode(AVLTree T,AVLTree v); //删除树,这里用不着
AVLTree InsertAVLTreeNode(AVLTree T, int v); //插入新的节点
int GetAVLTreeHeight(AVLTree T); //获取树的高度
int Max(int a, int b); //比较左子树高度和右子树高度,取高的那个。
int main()
{
int n, i, v;
AVLTree T;
cin >> n;
if( n == 0) //当输入n等于0
cout << 0 << endl;
else {
cin >> v; //先用一个节点建树
T = CreateAVLTreeNode(v);
for( i=1; i<n; i++) { //后面n-1个插入当中去。
cin >> v;
T = InsertAVLTreeNode(T, v);
}
cout << T->number << endl;
}
return 0;
}
AVLTree InsertAVLTreeNode(AVLTree T, int v)
{
AVLTree Tree;
if( T == NULL ) { //找到插入的位置了,建立节点进行插入。
T = CreateAVLTreeNode(v);
/*if( Tree == NULL ) {
cout << "未分配内存" << endl;
return NULL;
}*/
} else if( v < T->number ) { //当小于时,在左子树插入
T->left = InsertAVLTreeNode(T->left, v);
if( GetAVLTreeHeight(T->left) - GetAVLTreeHeight(T->right) == 2) { //插入之后,如果破坏了平衡,进行旋转
if( v > T->left->number ) //当插入的节点在左子树的右子树上,进行LR旋转
T = LeftRightRotation(T);
else //当插入的节点在左子树的左子树上,进行LL旋转
T = LeftLeftRotation(T);
}
} else if( v > T->number ) { //当大于时,在右子树插入。
T->right = InsertAVLTreeNode(T->right, v); //递归查找位置插入
if( GetAVLTreeHeight(T->right) - GetAVLTreeHeight(T->left) == 2) { //插入之后,如果破坏了平衡,进行旋转
if( v > T->right->number ) //当插入的节点在右子树的右子树上,进行RR旋转
T = RightRightRotation(T);
else //当插入的节点在右子树的左子树上,进行RL旋转
T = RightLeftRotation(T);
}
} /*else {
cout << "请不要添加相同节点!" << endl;
}*/
T->height = Max(GetAVLTreeHeight(T->left), GetAVLTreeHeight(T->right)) + 1; //更新树高。这里叶节点是1,因为结果有2个节点
/*cout << "The Root is " << T->number << endl << T->height << endl;*/ //根节点的高度应该是1,因为一边是0.所以叶节点也得是1.
return T;
}
AVLTree RightRightRotation(AVLTree T) //RR旋转,自己画个图可能更好理解一点。
{
AVLTree temp;
temp = T->right;
T->right = temp->left;
temp->left = T;
T->height = Max(GetAVLTreeHeight(T->left), GetAVLTreeHeight(T->right)) + 1;
temp->height = Max(T->height, GetAVLTreeHeight(temp->right)) + 1;
return temp;
}
AVLTree LeftLeftRotation(AVLTree T) //LL旋转
{
AVLTree temp;
temp = T->left;
T->left = temp->right;
temp->right = T;
T->height = Max(GetAVLTreeHeight(T->left), GetAVLTreeHeight(T->right)) + 1;
temp->height = Max(T->height, GetAVLTreeHeight(temp->left)) + 1;
return temp;
}
AVLTree LeftRightRotation(AVLTree T) //LR旋转,实际上就是左子树先进行RR旋转,再然后进行一次LL旋转。
{
T->left = RightRightRotation(T->left);
return LeftLeftRotation(T);
}
AVLTree RightLeftRotation(AVLTree T)//RL旋转,实际上就是右子树先进行LL旋转,再然后进行一次RR旋转。
{
T->right = LeftLeftRotation(T->right);
return RightRightRotation(T);
}
int Max(int a, int b) //求左右子树当中高的那个。
{
return (a>b)?a:b;
}
int GetAVLTreeHeight(AVLTree T) //求树的高度
{
int n;
if( T== NULL) //当没有儿子的时候,为0,即叶节点。
n = 0;
else
n = T->height;
return n;
}
AVLTree CreateAVLTreeNode(int v) //建立节点
{
AVLTree T = new (struct AVLTreeNode);
T->left = T->right = NULL;
T->height = 0;
T->number = v;
return T;
}