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
小结:
这道题是平衡二叉树的基本操作训练,应该是要熟练掌握的,第一遍写时大概花了2个小时,还是对着老师的课件写的,不是很满意,过两天再来重新写一遍,争取不看课件1个小时内写完;诸君共勉。
一个小困惑:
老师在结构体中加了一个Height,但是好像在后面的函数中都不需要用到这个值,都是靠函数递归,每次都遍历一遍来求各个树的高度;把这个值删了,完全不影响,先把这个困惑留着吧,或许后面会碰到需要这个值的情况
结构体+程序框架:个人还是习惯指针带*,所以没有像老师那样把指针定义为树
typedef struct _AVLNode* AVLTree;
#include <stdio.h>
#include <stdlib.h>
typedef struct _AVLNode AVLTree;
struct _AVLNode{
int Data;
AVLTree* Left;
AVLTree* Right;
// int Height;
};
int main()
{
int N;
scanf("%d",&N);
AVLTree* T = MakeAVLTree( N );
// printf("##\n");
printf("%d\n",T->Data);
FreeTree( T );
return 0;
}
1.建树函数
AVLTree* MakeAVLTree( int N )
{
AVLTree* T = NULL;
int X;
while(N--){
scanf("%d",&X);
T = Insert( T,X );
}
return T;
}
建树函数依靠一个个插入数据来完成
2.插入函数
AVLTree* Insert( AVLTree* T,int X )
{
if(!T){
T = (AVLTree*)malloc(sizeof(AVLTree));
T->Data = X;
T->Left = T->Right = NULL;
// T->Height = 0;
}else if(X < T->Data){
T->Left = Insert( T->Left,X );
T = IsRotation( T,X );
}else if(X > T->Data){
T->Right = Insert( T->Right,X );
T = IsRotation( T,X );
}
return T;
}
插入完成后立马判断是否需要旋转
3.旋转函数
AVLTree* IsRotation( AVLTree* T,int X )
{
if(GetHeight( T->Left ) - GetHeight( T->Right ) == 2){
if(X < T->Left->Data){
T = SingleLeftRotation( T );
}else if(X > T->Left->Data){
T = DoubleLeftRightRotation( T );
}
}else if(GetHeight( T->Right ) - GetHeight( T->Left ) == 2){
if(X > T->Right->Data){
T = SingleRightRotation( T );
}else if( X < T->Right->Data){
T = DoubleRightLeftRotation( T );
}
}
return T;
}
根据树高差判断是否需要旋转;
旋转有4种情况:左单旋、右单旋、左右双旋、右左双旋
4.求树高函数
int GetHeight( AVLTree* T )
{
int Height;
if(!T){
Height = 0;
}else if(T->Left && T->Right){
Height = Max( GetHeight( T->Left ),GetHeight( T->Right ) ) + 1;
}else if(T->Left && !(T->Right)){
Height = GetHeight( T->Left ) + 1;
}else if(T->Right && !(T->Left)){
Height = GetHeight( T->Right ) + 1;
}else{
Height = 1;
}
return Height;
}
int Max( int a,int b )
{
return a>b?a:b;
}
5.左单旋、右单旋、左右双旋、右左双旋--4种旋转函数
AVLTree* SingleLeftRotation( AVLTree* A )
{
AVLTree* B = A->Left;
A->Left = B->Right;
B->Right = A;
// A->Height = GetHeight( A );
// B->Height = GetHeight( B );
return B;
}
AVLTree* SingleRightRotation( AVLTree* A )
{
AVLTree* B = A->Right;
A->Right = B->Left;
B->Left = A;
// A->Height = GetHeight( A );
// B->Height = GetHeight( B );
return B;
}
AVLTree* DoubleLeftRightRotation( AVLTree* A )
{
A->Left = SingleRightRotation( A->Left );
AVLTree* C = SingleLeftRotation( A );
return C;
}
AVLTree* DoubleRightLeftRotation( AVLTree* A )
{
A->Right = SingleLeftRotation( A->Right );
AVLTree* C = SingleRightRotation( A );
return C;
}
6.最后释放动态内存:养成良好习惯,每次用到malloc,后面都要找机会free掉
void FreeTree( AVLTree* T )
{
if(T->Left){
FreeTree( T->Left);
}
if(T->Right){
FreeTree( T->Right );
}
free(T);
}
完整代码(C语言)
#include <stdio.h>
#include <stdlib.h>
typedef struct _AVLNode AVLTree;
struct _AVLNode{
int Data;
AVLTree* Left;
AVLTree* Right;
// int Height;
};
AVLTree* MakeAVLTree( int N );
AVLTree* Insert( AVLTree* T,int X );
int GetHeight( AVLTree* T );
int Max( int a,int b );
AVLTree* IsRotation( AVLTree* T,int X );
AVLTree* SingleLeftRotation( AVLTree* A );
AVLTree* SingleRightRotation( AVLTree* A );
AVLTree* DoubleLeftRightRotation( AVLTree* A );
AVLTree* DoubleRightLeftRotation( AVLTree* A );
void FreeTree( AVLTree* T );
int main()
{
int N;
scanf("%d",&N);
AVLTree* T = MakeAVLTree( N );
// printf("##\n");
printf("%d\n",T->Data);
FreeTree( T );
return 0;
}
AVLTree* MakeAVLTree( int N )
{
AVLTree* T = NULL;
int X;
while(N--){
scanf("%d",&X);
T = Insert( T,X );
}
return T;
}
AVLTree* Insert( AVLTree* T,int X )
{
if(!T){
T = (AVLTree*)malloc(sizeof(AVLTree));
T->Data = X;
T->Left = T->Right = NULL;
// T->Height = 0;
}else if(X < T->Data){
T->Left = Insert( T->Left,X );
T = IsRotation( T,X );
}else if(X > T->Data){
T->Right = Insert( T->Right,X );
T = IsRotation( T,X );
}
return T;
}
int GetHeight( AVLTree* T )
{
int Height;
if(!T){
Height = 0;
}else if(T->Left && T->Right){
Height = Max( GetHeight( T->Left ),GetHeight( T->Right ) ) + 1;
}else if(T->Left && !(T->Right)){
Height = GetHeight( T->Left ) + 1;
}else if(T->Right && !(T->Left)){
Height = GetHeight( T->Right ) + 1;
}else{
Height = 1;
}
return Height;
}
int Max( int a,int b )
{
return a>b?a:b;
}
AVLTree* IsRotation( AVLTree* T,int X )
{
if(GetHeight( T->Left ) - GetHeight( T->Right ) == 2){
if(X < T->Left->Data){
T = SingleLeftRotation( T );
}else if(X > T->Left->Data){
T = DoubleLeftRightRotation( T );
}
}else if(GetHeight( T->Right ) - GetHeight( T->Left ) == 2){
if(X > T->Right->Data){
T = SingleRightRotation( T );
}else if( X < T->Right->Data){
T = DoubleRightLeftRotation( T );
}
}
return T;
}
AVLTree* SingleLeftRotation( AVLTree* A )
{
AVLTree* B = A->Left;
A->Left = B->Right;
B->Right = A;
// A->Height = GetHeight( A );
// B->Height = GetHeight( B );
return B;
}
AVLTree* SingleRightRotation( AVLTree* A )
{
AVLTree* B = A->Right;
A->Right = B->Left;
B->Left = A;
// A->Height = GetHeight( A );
// B->Height = GetHeight( B );
return B;
}
AVLTree* DoubleLeftRightRotation( AVLTree* A )
{
A->Left = SingleRightRotation( A->Left );
AVLTree* C = SingleLeftRotation( A );
return C;
}
AVLTree* DoubleRightLeftRotation( AVLTree* A )
{
A->Right = SingleLeftRotation( A->Right );
AVLTree* C = SingleRightRotation( A );
return C;
}
void FreeTree( AVLTree* T )
{
if(T->Left){
FreeTree( T->Left);
}
if(T->Right){
FreeTree( T->Right );
}
free(T);
}