1123 Is It a Complete AVL Tree (AVL樹)
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 output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤ 20). 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, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print YES
NO
if not.
Sample Input 1:
5
88 70 61 63 65
Sample Output 1:
70 63 88 61 65
YES
Sample Input 2:
8
88 70 61 96 120 90 65 68
Sample Output 2:
88 65 96 61 70 90 120 68
NO
在左子樹的右結點 上新增一個new 結點
(1)
(2)
在右子樹的左子樹上 新增同理,分為兩種情況
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i=a;i<b;++i)
const int INF=0x3f3f3f3f;
const int N=50;
struct Node {
int x;
int b;
Node *l,*r;
};
int arr[N];
void R_Rotate(Node* &now)
{
Node* lc=now->l;
now->l=lc->r;
lc->r=now;
now=lc;
}
void L_Rotate(Node* &now)
{
Node* rc=now->r;
now->r=rc->l;
rc->l=now;
now=rc;
}
void bala_l(Node* &now)
{
Node* l=now->l,*rc=NULL;
switch(l->b) {
case 1:
now->b=l->b=0;
R_Rotate(now);
break;
case -1:
rc=l->r;
switch(rc->b) {
case 1:
l->b=0;
rc->b=0;
now->b=-1;
break;
//這裡也不能省略,可能出現下面這種情況
/*
x
/ \
x x
/
x
\
x
*/
case 0:
now->b=l->b=0;
break;
case -1:
l->b=1;
rc->b=0;
now->b=0;
break;
}
L_Rotate(now->l);
R_Rotate(now);
break;
}
}
void bala_r(Node* &now)
{
Node* r=now->r,*lc=r->l;
switch(r->b) {
case -1:
now->b=r->b=0;
L_Rotate(now);
break;
case 1:
lc=r->l;
switch(lc->b) {
case 1:
r->b=-1;
lc->b=0;
now->b=0;
break;
case 0:
now->b=r->b=0;
break;
case -1:
r->b=0;
lc->b=0;
now->b=1;
break;
}
R_Rotate(now->r);
L_Rotate(now);
break;
}
}
void insert_(Node* &now,int x,int& taller)
{
if(now==NULL) {
now=new Node;
now->x=x;
now->l=now->r=NULL;
now->b=0;
taller=1;
return;
}
if(x<=now->x) {
insert_(now->l,x,taller);
if(taller) {
switch(now->b) {
case -1:
now->b=0;
taller=0;
break;
case 0:
now->b=1;
break;
case 1:
// printf("***x:%d\n",now->x);
bala_l(now);
taller=0;
break;
}
}
} else {
insert_(now->r,x,taller);
if(taller) {
switch(now->b) {
case -1:
bala_r(now);
taller=0;
break;
case 0:
now->b=-1;
break;
case 1:
now->b=0;
taller=0;
break;
}
}
}
}
queue<Node*> q;
int n;
/*
最方便的是用到了引用,這樣的話,一顆子樹的旋轉就會很容易,指標的賦值就會比較方便
每次插入都得調整一下,路徑上點的平衡因子。
旋轉的話,只有兩種 L型和R型,細分又分為LR,LL。區別就是看看L那個子樹的平衡因子
*/
int res[N];
void bfs(Node* rt)
{
q.push(rt);
int cnt=0;
int wrong=0,f=0;
while(!q.empty()) {
Node* now=q.front();
q.pop();
res[cnt++]=now->x;
if(now->l)q.push(now->l);
if(now->r)q.push(now->r);
// printf("%d l:%x r:%x\n",now->x,now->l,now->r);
if(f&&(now->l!=NULL||now->r!=NULL))wrong=1;
if(now->l==NULL||now->r==NULL)f=1;
if(now->l==NULL&&now->r!=NULL)wrong=1;
}
// printf("***cnt:%d\n",cnt);
rep(i,0,cnt)printf("%d%c",res[i],i==cnt-1?'\n':' ');
if(wrong)printf("NO\n");
else printf("YES\n");
}
/*
3
1 2 3
3
3 2 1
5
88 70 61 63 65
6
88 70 61 96 120 90
*/
int main()
{
scanf("%d",&n);
rep(i,0,n)scanf("%d",&arr[i]);
Node *rt=NULL;//
int taller;
rep(i,0,n){
//printf("\n\n\n");
insert_(rt,arr[i],taller);
//bfs(rt);
}
bfs(rt);
return 0;
}