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 10^3 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
做了好久,看到中序和后序直接动态建树了,后面发现动态建树就是sb,因为后面需要靠值来找到这个结点。最后用了静态建树,中后也可以静态建树的,静态建树的话节点里面的左右子树存的都是下标值,我们这里用val直接当下标值,记得先将左右子树的设为-1,然后build函数返回值是int。
静态建完树就简单很多了,七种问题,是否为根结点,是否为兄弟,是否是父亲,是否是左孩子,是否是右孩子,是否同一层,是否是full二叉树,这个full二叉树真的要好好看题,什么鬼玩意,除了叶子结点每个结点都有左右子树就是full二叉树
通过bfs给每个结点父亲赋值,层级赋值,就可以做完大部分了。最后一个也在bfs里弄,如果又一个节点只有左or只有右,就让bfs返回一个false。
最后就是怎么获取问题了,
string question[10];
for(int j = 0;;j++){
cin>>question[j];
char c = getchar();
if(c == '\n') break;
}
我是这样写的,一开始用while循环,发现不能给每个单词赋值,因为读取到空格,会自动读取下一个字符串,所以弄一个字符串数组来存一句话里的每个单词,如果读到了换行符,就break。
然后就在字符串数组里找对应的单词即可
#include<iostream>//静态建树
#include<unordered_map>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
struct node{
int val;
int father;
int lchild=-1,rchild=-1;
int layer;
}tree[1005];
int n;
vector<int> postOrder(n+2);
vector<int> inOrder(n+2);
unordered_map<int,int> ma;
int buildTree(int postL, int postR,int inL, int inR){
if(postL > postR) return -1;
int root = postOrder[postR];
tree[root].val = root;
tree[root].lchild = tree[root].rchild = -1;
int leftSubTree = ma[root] - inL;
tree[root].lchild = buildTree(postL,postL + leftSubTree-1,inL,inL+leftSubTree-1);
tree[root].rchild = buildTree(postL+leftSubTree,postR-1,inL+leftSubTree+1,inR);
return root;
}
bool bfs(int s){
queue<int> q;
tree[s].layer = 1;
q.push(s);
bool flag = true;
while(!q.empty()){
int topNode = q.front();
q.pop();
bool flag1 = false, flag2 = false;//两个都为false证明都没有
if(tree[topNode].lchild != -1){
tree[tree[topNode].lchild].layer = tree[topNode].layer+1;
tree[tree[topNode].lchild].father = topNode;
q.push(tree[topNode].lchild);
flag1 = true;
}
if(tree[topNode].rchild != -1){
tree[tree[topNode].rchild].layer = tree[topNode].layer+1;
tree[tree[topNode].rchild].father = topNode;
q.push(tree[topNode].rchild);
flag2 = true;
}
if((flag1 == false && flag2 ==true) || (flag2 == false && flag1 ==true)) flag = false;
}
return flag;
}
int main(){
cin>>n;
for(int i = 0; i < n; i++){
cin>>postOrder[i];
}
for(int i = 0; i < n; i++){
cin>>inOrder[i];
}
for(int i = 0; i < n; i++){
ma[inOrder[i]] = i;
}
int root = buildTree(0,n-1,0,n-1);
bool f = bfs(root);
int q;
cin>>q;
int u,v;
for(int i = 0; i < n; i++){
string question[10];
for(int j = 0;;j++){
cin>>question[j];
char c = getchar();
if(c == '\n') break;
}
for(int j = 0; j < 10; j++){
if(question[j] == "root"){
u = stoi(question[0]);
if(root == u) cout<<"Yes\n";
else cout<<"No\n";
}
if(question[j] == "siblings"){//判断是否是兄弟结点,判断父亲是否是同一个,bfs中给父亲结点赋值
u = stoi(question[0]);
v = stoi(question[2]);
if(tree[u].father == tree[v].father) cout<<"Yes\n";
cout<<"No\n";
}
if(question[j] == "parent"){//判断是否是父亲
u = stoi(question[0]);
v = stoi(question[5]);
if(tree[v].father == u) cout<<"Yes\n";
else cout<<"No\n";
}
if(question[j] == "left"){//判断是否是左孩子
u = stoi(question[0]);
v = stoi(question[6]);
if(tree[v].lchild == u) cout<<"Yes\n";
else cout<<"No\n";
}
if(question[j] == "right"){//判断是否是右孩子
u = stoi(question[0]);
v = stoi(question[6]);
if(tree[v].rchild == u) cout<<"Yes\n";
else cout<<"No\n";
}
if(question[j] == "same"){//是否同一层
u = stoi(question[0]);
v = stoi(question[2]);
if(tree[u].layer == tree[v].layer) cout<<"Yes\n";
else cout<<"No\n";
}
if(question[j] == "full"){//是否是满二叉树,看倒数第二层的结点是否都有左右孩子
if(f) cout<<"Yes\n";
else cout<<"No\n";
}
}
}
return 0;
}
要通过值来找结点的话必须静态建树
//用静态建树,将值当做在数组中的下标,这样方便找这个结点
//兄弟就判断是否是同一个父亲,通过bfs给给每个父亲赋值,再给层赋值,再通过bfs判断每个结点是否都有两个子结点
#include<iostream>
#include<vector>
#include<unordered_map>
#include<queue>
using namespace std;
struct node{
int val;//通过val来找
int lchild,rchild;//子结点就是子结点的值,也就是子结点在数组中的下标
int father;
int layer;
}tree[1005];
vector<int> postOrder;
vector<int> inOrder;
unordered_map<int,int> ma;
bool flag = true;//如果是full树就是true
int buildTree(int postL,int postR,int inL,int inR){
if(postL > postR) return -1;//-1代表空结点
int root = postOrder[postR];
tree[root].lchild = tree[root].rchild = -1;
int subLeftTree = ma[postOrder[postR]] - inL;
tree[root].lchild = buildTree(postL,postL+subLeftTree-1,inL,inL+subLeftTree-1);
tree[root].rchild = buildTree(postL+subLeftTree,postR-1,inL+subLeftTree+1,inR);
return root;
}
void bfs(int s){
queue<int> q;
tree[s].layer = 1;
q.push(s);
while(!q.empty()){
bool haveL = false, haveR = false;
int topNode = q.front();
q.pop();
if(tree[topNode].lchild != -1){
haveL = true;
tree[tree[topNode].lchild].father = topNode;
tree[tree[topNode].lchild].layer = tree[topNode].layer+1;
q.push(tree[topNode].lchild);
}
if(tree[topNode].rchild != -1){
haveR = true;
tree[tree[topNode].rchild].father = topNode;
tree[tree[topNode].rchild].layer = tree[topNode].layer+1;
q.push(tree[topNode].rchild);
}
if((!haveL && haveR) || (!haveR && haveL)){
flag = false;
}
}
}
int main(){
int n;
cin>>n;
postOrder.resize(n+1);
inOrder.resize(n+1);
for(int i = 0; i < n; i++){
cin>>postOrder[i];
}
for(int i = 0; i < n; i++){
cin>>inOrder[i];
}
for(int i = 0; i < n; i++){
ma[inOrder[i]] = i;
}
int root = buildTree(0,n-1,0,n-1);
bfs(root);
string s[10];
int q;
cin>>q;
int u,v;
for(int i = 0; i < q; i++){
for(int j = 0; ;j++){
cin>>s[j];
char c = getchar();
if(c =='\n') break;
}
for(int j = 0; j < 10; j++){
if(s[j] == "root"){
u = stoi(s[0]);
if(root == u) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "siblings"){
u = stoi(s[0]);
v = stoi(s[2]);
if(tree[u].father == tree[v].father) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "parent"){
u = stoi(s[0]);
v = stoi(s[5]);
if(tree[v].father == u) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "left"){
u = stoi(s[0]);
v = stoi(s[6]);
if(tree[v].lchild == u) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "right"){
u = stoi(s[0]);
v = stoi(s[6]);
if(tree[v].rchild == u) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "same"){
u = stoi(s[0]);
v = stoi(s[2]);
if(tree[u].layer == tree[v].layer) cout<<"Yes\n";
else cout<<"No\n";
break;
}
if(s[j] == "full"){
if(flag) cout<<"Yes\n";
else cout<<"No\n";
break;
}
}
}
return 0;
}