题目翻译:
判断是否为完全平衡二叉树(满足完全二叉树+二叉搜索树+平衡树)
给定一个序列,按顺序插入到空树中,输出层序遍历结果,以及是否为完全二叉树(YES/NO)
题解思路:
这道题敲起来极其费劲,可以参考柳神的思路和代码:1123. Is It a Complete AVL Tree (30)-PAT甲级真题_1123甲级柳婼-CSDN博客
判断是不是完全二叉树,就看在出现了一个孩子为空的结点之后是否还会出现孩子结点不为空的结点,如果出现了就不是完全二叉树。
AVL树一共有四种情况,这里我把发现树不平衡的那个结点叫做A结点,A发现树不平衡的情况有四种:
新来的结点插入到A的左子树的左子树
新来的结点插入到A的左子树的右子树
新来的结点插入到A的右子树的左子树
新来的结点插入到A的右子树的右子树
发现不平衡时就需要处理,第1种情况只要简单的右旋,第4种情况只需左旋一下,第2种情况需要先对A的左子树左旋一下,然后对A右旋,同理第3种情况需要对A的右子树右旋一下,然后对A左旋就可以啦~~
代码:
#include<bits/stdc++.h>
using namespace std;
struct node{//定义树形节点
int val;
struct node *left,*right;
};
node* leftRotate(node *tree){//左旋部分
node *temp=tree->right;
tree->right=temp->left;
temp->left=tree;
return temp;
}
node* rightRotate(node *tree){//右旋部分
node *temp=tree->left;
tree->left=temp->right;
temp->right=tree;
return temp;
}
node* LeftRightRotate(node *tree){//左右旋
tree->left=leftRotate(tree->left);
return rightRotate(tree);
}
node *RightLeftRotate(node *tree){//右左旋
tree->right=rightRotate(tree->right);
return leftRotate(tree);
}
int getHeight(node *tree){//得到树的高度
if(tree==NULL)
return 0;
int l=getHeight(tree->left);
int r=getHeight(tree->right);
return max(l,r)+1;
}
node* insert(node *tree,int val){//树的插入部分
if(tree==NULL){//树为空的情况
tree=new node();
tree->val=val;
}else if(tree->val>val){//左子树进行插入
tree->left=insert(tree->left,val);
int l=getHeight(tree->left),r=getHeight(tree->right);
if(l-r>=2){//如果左右高度相差为2
if(val<tree->left->val)//如果小于树的左孩子,则进行右旋
tree=rightRotate(tree);
else//否则进行左右旋
tree=LeftRightRotate(tree);
}
}else{//右孩子进行插入
tree->right=insert(tree->right,val);
int l=getHeight(tree->left),r=getHeight(tree->right);
if(r-l>=2){//如果左右高度相差为2
if(val>tree->right->val)//如果大于树的右孩子,则进行左旋
tree=leftRotate(tree);
else//否则进行右左旋
tree=RightLeftRotate(tree);
}
}
return tree;//返回树的结点
}
int isComplete=1,after=0;//iscomplete为标记是否是完全二叉树,after为标记左右情况
vector<int> levelOrder(node *tree){//层序遍历
vector<int> v;
queue<node *> queue;
queue.push(tree);
while(!queue.empty()){
node *temp=queue.front();
queue.pop();
v.push_back(temp->val);
if(temp->left!=NULL){//确保从上到下,从左到右为满树
if(after)
isComplete=0;
queue.push(temp->left);
}else{
after=1;
}
if(temp->right!=NULL){
if(after)
isComplete=0;
queue.push(temp->right);
}else{
after=1;
}
}
return v;
}
int main(){
int n,temp;
cin>>n;
node *tree=NULL;
for(int i=0;i<n;i++){
cin>>temp;
tree=insert(tree,temp);//每次读入之后进行插入
}
vector<int> v=levelOrder(tree);//使用vector存储树的信息
for(int i=0;i<v.size();i++){
if(i!=0)
cout<<" ";
cout<<v[i];
}
printf("\n%s",isComplete?"YES":"NO");//是否是完全二叉树,进行输出
return 0;
}
坑点:
测试点2、3过不去可能是因为在插入的时候就计算结点高度了,忽略了旋转操作的影响