题目来源:中国大学MOOC-陈越、何钦铭-数据结构-2018春
作者: DS课程组
单位: 浙江大学
问题描述:
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
解答:
AVL树首先是一棵搜索树,所以根的左边都会比根小,根的右边都会比根大,尝试了下投机取巧排序输出中位数,这题能拿17分(逃
#include <algorithm>
using namespace std;
const int maxn=20;
int input[maxn];
int main()
{
int N;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>input[i];
}
sort(input,input+N);
if(N%2!=0)
cout<<input[(N-1)/2];
else
cout<<input[N/2];
return 0;
}
正经来说,需要建一棵AVL树,即在建立二叉搜索树的过程中,当插入一个节点递归调用返回上一层后,需要对当前根节点的左右子树高度进行判断,是否需要旋转。
当需要旋转时,判断是进行左旋左右旋还是右旋右左旋,即把哪个子节点提到根节点,并做相应变化:
可以设发现不平衡的节点称为节点A,新插入引起不平衡的节点称为节点B
A发现不平衡的情况有四种:
- B插入到A的左子树的左子树
- B插入到A的左子树的右子树
- B插入到A的右子树的左子树
- B插入到A的右子树的右子树
相对应的,第一种情况只需要左单旋(LL旋)即往右旋转,第四种情况只需要右单旋(RR旋)即往左旋转,比较难理解的是第二种和第四种情况。插入到A的左子树的右子树我们可以对A的左子树先右单旋一次,调整为需要左单旋的状态(LL状态),再整体对A左单旋一次,整体往右旋转调整;同理,插入到A的右子树的左子树,我们需要对A的右子树的左子树做一次向右旋转,调整为需要右单旋的状态(RR状态),右单旋即可。
旋转后要更新左右子树的高度值
head->height=maxHeight(getHeight(head->rightChild),getHeight(head->leftChild))+1;
当最后返回根节点时,一颗AVL树已经构造完毕。
#include <iostream>
using namespace std;
struct node
{
int value;
node* rightChild;
node* leftChild;
int height;
};
int maxHeight(int temp1,int temp2)
{
return temp1>temp2?temp1:temp2;
}
int getHeight(node* root)
{
if(root==NULL)
return 0;
else
return root->height;
}
node* RR(node* root)
{
node* temp=root;
root=root->rightChild;
temp->rightChild=root->leftChild;
root->leftChild=temp;
temp->height=maxHeight(getHeight(temp->rightChild),getHeight(temp->leftChild))+1;
root->height=maxHeight(getHeight(root->rightChild),getHeight(root->leftChild))+1;
return root;
}
node* LL(node* root)
{
node* temp=root;
root=root->leftChild;
temp->leftChild=root->rightChild;
root->rightChild=temp;
temp->height=maxHeight(getHeight(temp->rightChild),getHeight(temp->leftChild))+1;
root->height=maxHeight(getHeight(root->rightChild),getHeight(root->leftChild))+1;
return root;
}
node* RL(node* root)
{
root->rightChild=LL(root->rightChild);
return RR(root);
}
node* LR(node* root)
{
root->leftChild=RR(root->leftChild);
return LL(root);
}
node* buildTree(int value,node* head)
{
if(head==NULL)
{
node* temp=new node();
temp->value=value;
temp->height=1;
return temp;
}
if(value>head->value)
{
head->rightChild=buildTree(value,head->rightChild);
if(getHeight(head->rightChild)-getHeight(head->leftChild)==2)
{
if(value>head->rightChild->value)
{
head=RR(head);
}
else
{
head=RL(head);
}
}
}
else
{
head->leftChild=buildTree(value,head->leftChild);
if(getHeight(head->leftChild)-getHeight(head->rightChild)==2)
{
if(value<head->leftChild->value)
{
head=LL(head);
}
else
{
head=LR(head);
}
}
}
head->height=maxHeight(getHeight(head->rightChild),getHeight(head->leftChild))+1;
return head;
}
int main()
{
int N;
cin>>N;
node* tree=NULL;
for(int i=1;i<=N;i++)
{
int value;
cin>>value;
tree=buildTree(value,tree);
}
cout<<tree->value;
return 0;
}