这个题目的要点就是二叉平衡树,说白了就是让我们熟悉一下对二叉平衡树的操作。二叉平衡树就是在二叉树的基础上,需要满足每个节点的左子树和右子树的高度差不大于1.
也就是说,一旦出现差为2(或者-2)的情况,就需要对树进行调整。一共有四种调整方法,单左旋转,单右旋转,双左右旋转以及双右左旋转。其中,后面两个双旋转可以由前面两个单旋转拼接而成。因此,树的每个节点都必须带有一个表示自身高度的参数(height)。
在写这个程序的时候,我是按照这样的结构来写的,首先递归的写出构造二叉树的程序,其次,将四个旋转写成子函数的形式。困难的就是,在递归插入的同时,何时对这几旋转经行调用,彼此间如何区分,以及在旋转以及递归插入过程中,每个节点的高度如何及时更新。
何时经行调用的问题,即为左右子树高度差为2的情况。但为避免有-2出现,将其分为两段,若往左插入,则当左子树高度减右子树高度为2时调用;若往右插入,则当右子树高度减左子树高度为2时调用。
区分问题,主要是考虑单左旋转和双左右旋转(或者单右和双右左)旋转之间怎么分。仅以单左和双左右为例:可以利用插入元素第二次的去向来区分,假设元素已经往root的左子树插入,若其继续往root左子树的左子树插入,则是单左;若往root的左子树的右子树插入,则是双左右。单右和双右左同理。
高度处理。节点高度的变化一共在两个地方出现,一个是递归的插入,一个是旋转。在递归的插入时,只需要在返回节点之前对节点的高度刷新就好,旋转的位置,则需要在旋转完成,返回节点之前,对所有参加旋转的节点的高度刷新。由于双旋转可以调用单旋转来完成,所以仅需要在单旋转内进行刷新就好。
下面是程序:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct _node{
int data;
int height;
struct _node *left;
struct _node *right;
}Node;
Node* creat_node();
int find_height(Node* node);
Node* insert_node(Node* root,int tmp);
void free_tree(Node *root);
int max_height(Node *a,Node *b);
Node* singleleft(Node *root);
Node* singleright(Node *root);
Node* doubleleft(Node* root);
Node* doubleright(Node* root);
int main(){
Node *root=NULL;
int i=0;
int number=0;
int times=0;
scanf("%d",×);
for(i=0;i<times;i++){
scanf("%d",&number);
root=insert_node(root,number);
}
printf("%d",root->data);
return 0;
}
Node* insert_node(Node* root,int tmp){
if(root==NULL){
root=creat_node();
root->data=tmp;
}
else
{
if(tmp > root->data){
root->right=insert_node(root->right,tmp);
if(find_height(root->right)-find_height(root->left)==2){
if(tmp > root->right->data){
root=singleright(root);
}
else
{
root=doubleright(root);
}
}
}
else{
if(tmp<root->data){
root->left=insert_node(root->left,tmp);
if(find_height(root->left)-find_height(root->right)==2){
if(tmp < root->left->data){
root=singleleft(root);
}
else
{
root=doubleleft(root);
}
}
}
}
}
root->height=max_height(root->left,root->right)+1;
return root;
}
Node* singleleft(Node *root){
Node *k1=root->left;
root->left=k1->right;
k1->right=root;
root->height=max_height(root->left,root->right)+1;
k1->height=max_height(k1->left,k1->right)+1;
return k1;
}
Node* singleright(Node *root){
Node *k2=root->right;
root->right=k2->left;
k2->left=root;
root->height=max_height(root->left,root->right)+1;
k2->height=max_height(k2->left,k2->right)+1;
return k2;
}
Node* doubleleft(Node *root){
root->left=singleright(root->left);
return singleleft(root);
}
Node* doubleright(Node *root){
root->right=singleleft(root->right);
Node *p=singleright(root);
return p;
}
int max_height(Node *a,Node *b){
int i=find_height(a);
int j=find_height(b);
if(i>j)
{
return i;
}
else
{
return j;
}
}
void free_tree(Node *root){
if(root){
free_tree(root->left);
free_tree(root->right);
}
free(root);
}
Node* creat_node(){
Node *p=(Node*)malloc(sizeof(Node));
p->data=0;
p->height=0;
p->left=NULL;
p->right=NULL;
return p;
}
int find_height(Node* node){
int height;
if(node){
height=node->height;
}
else
{
height=-1;
}
return height;
}
题目:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
04-树5 Root of AVL Tree (25分)
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 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