MOOC 04-树5 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

 小结:

这道题是平衡二叉树的基本操作训练,应该是要熟练掌握的,第一遍写时大概花了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);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值