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
Show me the Code:
#include <stdio.h>
#include <stdlib.h>
#ifndef _AvlTree_H
struct AvlNode;
typedef int ElementType;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;
AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType X,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType X,AvlTree T);
AvlTree Delete(ElementType X,AvlTree T);
ElementType Retrieve(Position P);
#endif // _AvlTree_H
#ifndef NULL
#define NULL 0
#endif // NULL
struct AvlNode
{
ElementType Element;
AvlTree Left;
AvlTree Right;
int Height;
};
int Max(int,int);
static int Height(Position);
AvlTree Insert(ElementType,AvlTree);
AvlTree SingleRotateWithLeft(AvlTree T);
AvlTree SingleRotateWithRight(AvlTree T);
AvlTree DoubleRotateWithLeft(AvlTree T);
AvlTree DoubleRotateWithRight(AvlTree T);
int main()
{
AvlTree T = NULL;
int i,N;
ElementType X;
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%d",&X);
T = Insert(X,T);
}
printf("%d",T->Element);
}
static int Height(Position P)
{
if(P == NULL)
return -1;
else
return P->Height;
}
AvlTree Insert(ElementType X, AvlTree T)
{
if(T == NULL)
{
T = (AvlTree)malloc(sizeof(struct AvlNode));
if(T == NULL)
printf("Out of space.");
else
{
T->Element = X;
T->Height = 0;
T->Left = NULL;
T->Right = NULL;
}
}
else
{
if(X < T->Element)
{
T->Left = Insert(X,T->Left);
if(Height(T->Left)-Height(T->Right) == 2){
if(X < T->Left->Element)
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
}
else if(X>T->Element)
{
T->Right = Insert(X,T->Right);
if(Height(T->Right)-Height(T->Left) == 2){
if(X < T->Right->Element) //第一处不一样
T = DoubleRotateWithRight(T);
else
T = SingleRotateWithRight(T);
}
}
}
T->Height = Max(Height(T->Left),Height(T->Right)) + 1;
return T;
}
int Max(int a,int b)
{
return (a > b) ? a : b;
}
Position SingleRotateWithLeft(Position K2)
{
Position K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2;
K2->Height = Max(Height(K2->Left),Height(K2->Right)) + 1;
K1->Height = Max(Height(K1->Left),Height(K1->Right)) + 1;
return K1;
}
Position SingleRotateWithRight(Position K2)
{
Position K1;
K1 = K2->Right;
K2->Right = K1->Left;
K1->Left = K2;
K2->Height = Max(Height(K2->Left),Height(K2->Right)) + 1;
K1->Height = Max(Height(K1->Left),Height(K1->Right)) + 1;
return K1;
}
Position DoubleRotateWithLeft(Position K2)
{
Position K1, K3;
K1 = K2->Left;
K3 = K1->Right;
K2->Left = K3->Right;
K1->Right = K3->Left;
K3->Left = K1;
K3->Right = K2;
K1->Height = Max(Height(K1->Left),Height(K1->Right)) + 1;
K2->Height = Max(Height(K2->Left),Height(K2->Right)) + 1;
K3->Height = Max(Height(K3->Left),Height(K3->Right)) + 1;
return K3;
}
Position DoubleRotateWithRight(Position K2)
{
Position K1, K3;
K1 = K2->Right;
K3 = K1->Left;
K2->Right = K3->Left;
K1->Left = K3->Right;
K3->Left = K2;
K3->Right = K1;
K1->Height = Max(Height(K1->Left),Height(K1->Right)) + 1;
K2->Height = Max(Height(K2->Left),Height(K2->Right)) + 1;
K3->Height = Max(Height(K3->Left),Height(K3->Right)) + 1;
return K3;
}
运行结果:
思路与问题
AVL树的插入和建立过程中,遇到的调整情况分为四类:
1. 麻烦节点出现在左子树的左子树上,此时使用LL变换,将中间的结点变为根节点
2. 麻烦节点出现在右子树的右子树上,此时使用RR变换。。。
3. 麻烦节点出现在左子树的右子树上,这时单边的变换已经没有用了,可以将麻烦节点变为根节点,并调整树向左边增加层数或向右边增加层数。
4. 麻烦节点出现在右子树的左子树上。。。