PTA || 04-樹5 Root of AVL Tree
阿新 • • 發佈:2018-12-17
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.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer NNN (≤20\le 20≤20) 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; }