1123 Is It a Complete AVL Tree (30分)
判断是否为完全平衡二叉树(满足完全二叉树+二叉搜索树+平衡树)
题目大意:给定一个序列,按顺序插入到空树中,输出层序遍历结果,以及是否为完全二叉树(YES/NO)
-
如果不太懂AVL树,以及旋转规则等,可以去中国大学mooc上看看浙江大学的《数据结构》课程( 传送门0 ),在第四讲(树(中))。老师讲得很好,也有代码实现,这里就不赘述啦~
-
判断是否为完全二叉树,我采用的是层序遍历,这样就可以一边输出一边判断( 和甲级的另外一题 1110 Complete Binary Tree (25分) 一样的方法,可以看这篇(传送门1,也是我的题解)。
#include<iostream> //输入输出流头文件
#include<math.h> //数学函数
#include<queue> //队列
using namespace std; //标准命名空间
typedef struct avl{
int elem;
avl* left,*right;
avl(int e){this->elem=e;this->left=NULL;this->right=NULL;}
};
int n,r;
avl* insertAVL(avl *t,int e);//插入新结点
avl* createAVLTree(avl *t);
void levelorderAVL(avl *t);
int main(){ //主函数
#ifdef ONLINE_JUDGE //如果有oj系统(在线判定),则忽略文件读入,否则使用文件作为标准输入
#else
freopen("1.txt", "r", stdin); //从1.txt输入数据
#endif
cin>>n>>r;
avl* t=new avl(r);
t= createAVLTree(t);//建树
levelorderAVL(t);//层序遍历
return 0; //返回0,如果不返回0,PAT会报错
}
void levelorderAVL(avl *t){//层序遍历
queue<avl*> q;
int flag=1,isbinaryt=1;//判断是否出现空结点,判断是否为完全二叉树
avl* p=t;
q.push(p);
while(!q.empty()){
if(p->left) {
q.push(p->left);
if(flag==0) isbinaryt=0;//如果前面出现空结点,说明不为完全二叉树
}
else flag=0;
if(p->right){
q.push(p->right);
if(flag==0) isbinaryt=0;
}
else flag=0;
q.pop();
cout<<p->elem;
if(!q.empty()){
cout<<' ';
p=q.front();
}
else cout<<endl;
}
if(isbinaryt)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int getHeight(avl *t){//计算高度
if(t){
int lh=getHeight(t->left)+1;
int rh=getHeight(t->right)+1;
return lh>rh?lh:rh;
}
else return 0;
}
avl* createAVLTree(avl *t){
for(int i=1;i<n;i++){
int e;cin>>e;
t=insertAVL(t,e) ;//插入
}
return t;
}
avl* ll(avl *t){//左左
avl *p=t->left;//保存旋转后的根结点
t->left=p->right;
p->right=t;
return p;
}
avl *rr(avl *t){//右右
avl *p=t->right;
t->right=p->left;
p->left=t;
return p;
}
avl *lr(avl *t){//左右
avl *p=t->left;
avl *q=t->left->right;
p->right=q->left;
t->left=q->right;
q->left=p;
q->right=t;
return q;
}
avl* rl(avl *t){//右左
avl *p=t->right;
avl *q=t->right->left;
p->left=q->right;
t->right=q->left;
q->left=t;
q->right=p;
return q;
}
avl* insertAVL(avl *t,int e){
if(t==NULL) {t=new avl(e);return t;}//新建一个结点,并返回
if(e<=t->elem){
t->left=insertAVL(t->left,e);//进入左边
if(abs(getHeight(t->left)-getHeight(t->right))>1){//每一层递归出来检查当前结点高度差
if(e<=t->left->elem)t=ll(t);//左左旋
else t=lr(t) ;//左右旋
}
}
else{
t->right=insertAVL(t->right,e);
if(abs(getHeight(t->left)-getHeight(t->right))>1){
if(e>t->right->elem)t=rr(t) ;//右右旋
else t=rl(t);//右左旋
}
}
return t;
}