Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, a binary tree can be uniquely determined.
Now given a sequence of statements about the structure of the resulting tree, you are supposed to tell if they are correct or not. A statment is one of the following:
- A is the root
- A and B are siblings
- A is the parent of B
- A is the left child of B
- A is the right child of B
- A and B are on the same level
- It is a full tree
Note:
- Two nodes are on the same level, means that they have the same depth.
- A full binary tree is a tree in which every node other than the leaves has two children.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are no more than 103 and are separated by a space.
Then another positive integer M (≤30) is given, followed by M lines of statements. It is guaranteed that both A
and B
in the statements are in the tree.
Output Specification:
For each statement, print in a line Yes
if it is correct, or No
if not.
Sample Input:
9
16 7 11 32 28 2 23 8 15
16 23 7 32 11 2 28 15 8
7
15 is the root
8 and 2 are siblings
32 is the parent of 11
23 is the left child of 16
28 is the right child of 2
7 and 11 are on the same level
It is a full tree
Sample Output:
Yes
No
Yes
No
Yes
Yes
Yes
题目大意:给一个后序和中序序列构成一棵树,让你然后判断一些语句的对错。
语句类型:
- A is the root
- A and B are siblings (siblings:兄弟)
- A is the parent of B
- A is the left child of B
- A is the right child of B
- A and B are on the same level
- It is a full tree
分析:
1)数据结构定义
静态链表和二叉链表都可以,这里采用二叉链表存储。便于判断父子关系和结点level,结构体这样定义;
struct node{
int val,level;
node* parent;
node* l,*r;
};
2)建树
对往常后序和中序建树模板稍加改动即可:模板
在创建过程存储下当前val域与root指针的映射关系:nodes[root->val]=root(因为判断语句采用nodes【】判断),并将孩子结点的parent域(孩子结点非空)指向root即可 (emmm,突然发现个小bug,如果有root->val,那指针就覆盖了)
核心代码:
node *creat(int postl,int postr,int inl,int inr){
if(postl>postr) return NULL;
node *root=new node;
root->val=post[postr];
nodes[root->val]=root; //存指针
int k=inl;
while(k<=inr && in[k]!=root->val) k++;
int leftnum=k-inl;
root->l =creat(postl,postl+leftnum-1,inl,k-1);
root->r =creat(postl+leftnum,postr-1,k+1,inr);
if (root->l) root->l->parent=root;
if (root->r) root->r->parent=root;
return root;
}
3)遍历树获取有效信息
前面两部已经获取到了父子关系啥的,现在只需要遍历过程得到高度和进行full tree判断,那么深搜一下即可。对于full tree判断这里采用反证法 (初始化is_full=true)
void dfs(node* root){ //获得高度和full树判断
if (!root) return;
if (root->parent) root->level=root->parent->level+1; //根节点没有parent,得判断
if (root->l && !root->r) is_full=false;//只有左子树或者右子树则不是full tree
if (!root->l && root->r) is_full=false;
dfs(root->l);
dfs(root->r);
}
4)判断语句读取
如果常规cin>>str,那么肯定要写很多if else判断 ,容易搞混且代码不简洁,这里采用sscanf()大法:更多介绍
一点说明:sscanf() - 从一个字符串中读进与指定格式相符的数据.
函数原型:
int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
int scanf( const char *format [,argument]... );
说明:
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
读入示例:
if (str.find("left child") != string::npos) {
sscanf(str.c_str(), "%d is the left child of %d", &a, &b);
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=50;
struct node{
int val,level;
node* parent;
node* l,*r;
};
bool is_full=true;
unordered_map<int, node*> nodes;
int post[maxn],in[maxn];
node *creat(int postl,int postr,int inl,int inr){
if(postl>postr) return NULL;
node *root=new node;
root->val=post[postr];
nodes[root->val]=root; //存指针
int k=inl;
while(k<=inr && in[k]!=root->val) k++;
int leftnum=k-inl;
root->l =creat(postl,postl+leftnum-1,inl,k-1);
root->r =creat(postl+leftnum,postr-1,k+1,inr);
if (root->l) root->l->parent=root;
if (root->r) root->r->parent=root;
return root;
}
void dfs(node* root){ //获得高度和full树判断
if (!root) return;
if (root->parent) root->level=root->parent->level+1;
if (root->l && !root->r) is_full=false;
if (!root->l && root->r) is_full=false;
dfs(root->l);
dfs(root->r);
}
int main(){
int m,n;
cin>>n;
for(int i=0;i<n;i++) cin>>post[i];
for(int i=0;i<n;i++) cin>>in[i];
node* root=creat(0,n-1,0,n-1);
root->level=1;
dfs(root);
cin>>m;
getchar();
while(m--){
bool flag;
int a,b;
string str;
getline(cin, str);
if(str.find("root")!=string::npos){
sscanf(str.c_str(),"%d is the root",&a);
flag=(a==root->val)?1:0;
}else if(str.find("siblings")!=string::npos){
sscanf(str.c_str(), "%d and %d are siblings",&a,&b);
flag=(nodes[a]->parent==nodes[b]->parent)?1:0;
}else if(str.find("parent")!=string::npos){
sscanf(str.c_str(),"%d is the parent of %d",&a,&b);
flag=(nodes[b]->parent==nodes[a])? 1:0;
}else if(str.find("left child")!=string::npos){
sscanf(str.c_str(),"%d is the left child of %d",&a,&b);
flag=(nodes[b]->l==nodes[a])? 1:0;
}else if(str.find("right child")!=string::npos){
sscanf(str.c_str(), "%d is the right child of %d",&a,&b);
flag=(nodes[b]->r==nodes[a])? 1:0;
}else if(str.find("same level")!=string::npos){
sscanf(str.c_str(), "%d and %d are on the same level", &a, &b);
flag=(nodes[a]->level==nodes[b]->level)? 1:0;
}else{
flag=is_full;
}
cout<<(flag?"Yes" : "No")<<endl;
}
return 0;
}