1. 程式人生 > >PTA || 04-樹5 Root of AVL Tree

PTA || 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 NNN (≤20\le 2020) which is the total number of keys to be inserted. Then NNN 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
#include <stdio.h>
#include <stdlib.h>
#define ElementType int

//AVL樹結點定義 
typedef struct AVLNode *Position;
typedef Position AVLTree;//AVL樹的型別 
struct AVLNode {
	ElementType Data;//結點資料
	AVLTree Left;
	AVLTree Right;
	int Height; 
};

/************************************************************** 
1.插入新結點,判斷樹是否為空,若為空則建立以新節點為根的新AVL樹 ; 
2.若不為空,將新結點與現有結點比較後遞迴插入左或右子樹 ;
3.判斷樹高,若破壞平衡,則根據樹高判斷進行以下哪種旋轉:
(1)SingleLeftRotation
(2)SingleRightRotation
(3)DoubleLeftRightRotation
(4)DoubleRightLeftRotation 
**************************************************************/
AVLTree Insert(AVLTree A, ElementType X);//結點插入AVL樹 
int GetTreeHeight(AVLTree A);//得到樹的高度  
AVLTree SingleLeftRotation(AVLTree A);//左單旋
AVLTree SingleRightRotation(AVLTree A);//右單旋
AVLTree DoubleLeftRightRotation(AVLTree A);//左-右雙旋 
AVLTree DoubleRightLeftRotation(AVLTree A);//右-左雙旋 
int Max(int a, int b);//獲取左右子樹高度最大值

//主體程式框架 
int main()
{
	AVLTree A;
	int N, i;
	int x;
	A = (AVLTree)malloc(sizeof(struct AVLNode));
	scanf("%d\n", &N);
	scanf("%d", &x);
	A->Data = x;
	A->Left = A->Right = NULL;
	A->Height = 1;
	for (i=1; i<N; i++){
		scanf("%d", &x);
		A = Insert(A, x);
	}
	printf("%d\n", A->Data );
	
	return 0;
}

AVLTree Insert(AVLTree A, ElementType X)
//結點插入AVL樹 
{
	if (!A){ //樹為空 
		A = (AVLTree)malloc(sizeof(struct AVLNode));
		A->Data = X;
		A->Left = A->Right = NULL;
		A->Height = 1;
	}
	//樹不空 
	else if (X < A->Data ){
	//插入A的左子樹 
		A->Left = Insert(A->Left , X);
		if (GetTreeHeight(A->Left ) - GetTreeHeight(A->Right ) == 2){
		//如果需要進行左旋 
			if (X < A->Left->Data )//左單旋 
				A = SingleLeftRotation(A);
			else    //左-右雙旋 
				A = DoubleLeftRightRotation(A);	
		}
	}
	else if (X >A->Data ){
	//插入A的右子樹 
		A->Right = Insert(A->Right , X);
		if (GetTreeHeight(A->Left ) - GetTreeHeight(A->Right ) == -2){
		//如果需要進行右旋 
			if (X > A->Right->Data )  //右單旋 
				A = SingleRightRotation(A);
			else   //右-左雙旋 
				A = DoubleRightLeftRotation(A);
		}
	}//X = A->Data不用插入
	A->Height = Max(GetTreeHeight(A->Left ), GetTreeHeight(A->Right )) + 1;//更新樹高 
	
	return A;
}

int GetTreeHeight(AVLTree A)
//遞迴得到樹的高度
{
	int HL, HR, H;
	if (!A) return 0;
	else{
		HL = GetTreeHeight(A->Left );
		HR = GetTreeHeight(A->Right );
		H = Max(HL, HR);
		
		return (H+1);
	}
 } 

AVLTree SingleLeftRotation(AVLTree A)
//左單旋,A必須有一個左子結點B
//左旋時,A的左子結點B的左子樹不動,A的右子樹不動 
{
	AVLTree B = A->Left ;
	A->Left = B->Right ;
	B->Right = A;
	A->Height = Max(GetTreeHeight(A->Left ),GetTreeHeight(A->Right )) + 1;
	B->Height = Max(GetTreeHeight(B->Left ),A->Height )+ 1;
	
	return B;
}

AVLTree SingleRightRotation(AVLTree A)
//右單旋,A必須有一個右子結點B
//右旋時,A的右子結點B的右子樹不動,A的左子樹不動 
{
	AVLTree B = A->Right ;
	A->Right = B->Left ;
	B->Left = A;
	A->Height = Max(GetTreeHeight(A->Left ),GetTreeHeight(A->Right )) + 1;
	B->Height = Max(GetTreeHeight(B->Right ),A->Height) + 1;
	
	return B;
} 

AVLTree DoubleLeftRightRotation(AVLTree A)
//左-右雙旋,A必須有一個左子結點B,B必須有一個右子結點C 
{
	//B與C做一次右單旋,C被返回
	AVLTree B = A->Left ;
	AVLTree C = B->Right ;
	A->Left = SingleRightRotation(B);
	//A與C做一次左單旋,C被返回
	return SingleLeftRotation(A);  
}

AVLTree DoubleRightLeftRotation(AVLTree A)
//右-左雙旋,A必須有一個右子結點B,B必須有一個左子結點C
{
	//B與C做一次左單旋,C被返回 
	AVLTree B = A->Right ;
	AVLTree C = B->Left ;
	A->Right = SingleLeftRotation(B);
	//A與C做一次右單旋,C被返回
	return SingleRightRotation(A); 
} 

int Max(int a, int b)
//比較大小,返回最大值
{
	return a > b ? a : b;
}