PAT甲级【2019年3月考题】——A1159 Structure_of_a_BinaryTree【30】
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 10^310
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
【声明】
由于此题还未上PAT官网题库,故没有测试集,仅仅是通过了样例,若发现错误,感谢留言指正。
Solution:
这道题不难,先通过后序和中序重构整颗二叉树,在重构时,使用hash表来存储每个节点值对应的节点,这样就可以解决后面询问是不是父节点和左右子节点的问题。
然后使用DFS来遍历整棵树,得到每个节点的深度值,其中记得记录每个节点的姐妹节点是谁,并进行判断是不是完整二叉树。
到此,对于题目中的7个问题都有相应的记录进行解决
唯一麻烦的是,对于问题的处理,题目是输入一整句话,那么判断属于哪个问题和将其中的关键数字取出来就比较麻烦,我是使用string中的find来判断属于哪个问题,并使用循环来获取数字,当然你也可以使用istringstream函数进行切割获取数据。
1 #include <iostream> 2 #include <queue> 3 #include <vector> 4 #include <string> 5 #include <unordered_map> 6 using namespace std; 7 struct Node 8 { 9 int val; 10 Node *l, *r; 11 Node(int a = 0) :val(a), l(nullptr), r(nullptr) {} 12 }; 13 int n, m; 14 bool isfullTree = true; 15 vector<int>post, in, siblings(1010, -1), level(1010, -1); 16 unordered_map<int, Node*>map; 17 Node* creatTree(int inL, int inR, int postL, int postR)//重建二叉树 18 { 19 if (inL > inR) 20 return nullptr; 21 Node *root = new Node(post[postR]); 22 map[root->val] = root;//记录节点对应的key值 23 int k = inL; 24 while (k <= inR && in[k] != post[postR])++k; 25 int nums = k - inL; 26 root->l = creatTree(inL, k - 1, postL, postL + nums - 1); 27 root->r = creatTree(k + 1, inR, postL + nums, postR - 1); 28 return root; 29 } 30 void DFS(Node *root, int L) 31 { 32 if (root == nullptr) 33 return; 34 if ((root->l == nullptr && root->r) || (root->r == nullptr && root->l)) 35 isfullTree = true;//不是完全二叉树 36 level[root->val] = L;//记录层数 37 if (root->l&& root->r)//记录姐妹节点 38 { 39 siblings[root->l->val] = root->r->val; 40 siblings[root->r->val] = root->l->val; 41 } 42 DFS(root->l, L + 1); 43 DFS(root->r, L + 1); 44 } 45 vector<int> getNumber(const string &str, bool isOneNumber)//获取数据 46 { 47 vector<int>res; 48 int a = 0; 49 for (int i = 0; i < str.length(); ++i) 50 { 51 if (isdigit(str[i])) 52 a = a * 10 + str[i] - '0'; 53 else if (a > 0) 54 { 55 res.push_back(a); 56 a = 0; 57 if (isOneNumber || res.size() == 2)//就输出一个字符就行 58 break; 59 } 60 } 61 if (!isOneNumber && res.size() < 2)//获取处于最后的数字 62 res.push_back(a); 63 return res; 64 } 65 int main() 66 { 67 cin >> n; 68 post.resize(n); 69 in.resize(n); 70 for (int i = 0; i < n; ++i) 71 cin >> post[i]; 72 for (int i = 0; i < n; ++i) 73 cin >> in[i]; 74 Node *root = creatTree(0, n - 1, 0, n - 1); 75 DFS(root, 1);//获取层数 76 cin >> m; 77 getchar(); 78 while (m--) 79 { 80 string str; 81 getline(cin, str); 82 if (str.find("root", 0) != -1)//查询根节点 83 { 84 vector<int>res = getNumber(str, true); 85 if (root->val == res[0]) 86 printf("Yes\n"); 87 else 88 printf("No\n"); 89 } 90 else if (str.find("siblings", 0) != -1)//查询姐妹节点 91 { 92 vector<int>res = getNumber(str, false); 93 if (siblings[res[0]] == res[1]) 94 printf("Yes\n"); 95 else 96 printf("No\n"); 97 } 98 else if (str.find("parent", 0) != -1)//查询父节点 99 { 100 vector<int>res = getNumber(str, false); 101 if ((map[res[0]]->l && map[res[0]]->l->val == res[1]) || 102 (map[res[0]]->r && map[res[0]]->r->val == res[1])) 103 printf("Yes\n"); 104 else 105 printf("No\n"); 106 } 107 else if (str.find("left", 0) != -1)//左节点 108 { 109 vector<int>res = getNumber(str, false); 110 if (map[res[1]]->l && map[res[1]]->l->val == res[0]) 111 printf("Yes\n"); 112 else 113 printf("No\n"); 114 } 115 else if (str.find("right", 0) != -1)//右节点 116 { 117 vector<int>res = getNumber(str, false); 118 if (map[res[1]]->r && map[res[1]]->r->val == res[0]) 119 printf("Yes\n"); 120 else 121 printf("No\n"); 122 } 123 else if (str.find("level", 0) != -1)//同样的深度 124 { 125 vector<int>res = getNumber(str, false); 126 if (level[res[0]]==level[res[1]]) 127 printf("Yes\n"); 128 else 129 printf("No\n"); 130 } 131 else if (str.find("full", 0) != -1)//是不是完整二叉树 132 { 133 if (isfullTree) 134 printf("Yes\n"); 135 else 136 printf("No\n"); 137 } 138 } 139 return 0; 140 }
我的代码有点繁琐,后然我逛博客发现了一个更简便的字符处理函数sscanf,还有就是由于重构二叉树的同时就是一个DFS的过程,这样我们就可以将其深度值得到。当然,我感觉我的代码还是有点优点的,不是么 ^_^.
附带博主代码:
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<algorithm> 5 #include<string> 6 #include<cstring> 7 #include<unordered_map> 8 #include<unordered_set> 9 using namespace std; 10 const int maxn=1005; 11 const int INF=0x3f3f3f3f; 12 unordered_map<int,int> level,parents; 13 struct node { 14 int data; 15 int layer; 16 node *lchild,*rchild; 17 }; 18 vector<int> post,in; 19 node* newNode(int data,int layer) { 20 node* root=new node; 21 root->data=data; 22 root->layer=layer; 23 level[data]=layer; 24 root->lchild=root->rchild=NULL; 25 return root; 26 } 27 bool flag=true; 28 node* create(int parent,int postLeft,int postRight,int inLeft,int inRight,int layer) { 29 if(postLeft>postRight) return NULL; 30 node* root=newNode(post[postRight],layer); 31 parents[root->data]=parent; 32 int index=inLeft; 33 while(in[index]!=root->data) index++; 34 int numLeft=index-inLeft; 35 root->lchild=create(root->data,postLeft,postLeft+numLeft-1,inLeft,index-1,layer+1); 36 root->rchild=create(root->data,postLeft+numLeft,postRight-1,index+1,inRight,layer+1); 37 //如果有叶子,就必须有两片叶子 38 if((root->lchild || root->rchild ) && (!root->lchild || !root->rchild)) flag=false; 39 return root; 40 } 41 int main() { 42 int n,m; 43 unordered_map<int,int> ppos,ipos; 44 scanf("%d",&n); 45 post.resize(n); 46 in.resize(n); 47 for(int i=0; i<n; i++) { 48 scanf("%d",&post[i]); 49 ppos[post[i]]=i; 50 } 51 for(int i=0; i<n; i++) { 52 scanf("%d",&in[i]); 53 ipos[in[i]]=i; 54 } 55 node* root = create(n-1,0,n-1,0,n-1,0); 56 scanf("%d\n",&m); 57 string ask; 58 for(int i=0; i<m; i++) { 59 getline(cin,ask); 60 int num1=0,num2=0; 61 if(ask.find("root")!=string::npos) { 62 sscanf(ask.c_str(),"%d is the root",&num1); 63 if(ppos[num1]==n-1) puts("Yes"); 64 else puts("No"); 65 } else if(ask.find("siblings")!=string::npos) { 66 sscanf(ask.c_str(),"%d and %d are siblings",&num1,&num2); 67 if(level[num1]==level[num2] && parents[num1]==parents[num2]) puts("Yes"); 68 else puts("No"); 69 } else if(ask.find("parent")!=string::npos) { 70 sscanf(ask.c_str(),"%d is the parent of %d",&num1,&num2); 71 if(parents[num2]==num1) puts("Yes"); 72 else puts("No"); 73 } else if(ask.find("left")!=string::npos) { 74 sscanf(ask.c_str(),"%d is the left child of %d",&num1,&num2); 75 if(parents[num1]==num2 && ipos[num1]<ipos[num2]) puts("Yes"); 76 else puts("No"); 77 } else if(ask.find("right")!=string::npos) { 78 sscanf(ask.c_str(),"%d is the right child of %d",&num1,&num2); 79 if(parents[num1]==num2 && ipos[num1]>ipos[num2]) puts("Yes"); 80 else puts("No"); 81 } else if(ask.find("same")!=string::npos) { 82 sscanf(ask.c_str(),"%d and %d are on the same level",&num1,&num2); 83 if(level[num1]==level[num2]) puts("Yes"); 84 else puts("No"); 85 } else if(ask.find("full")!=string::npos) { 86 if(flag) puts("Yes"); 87 else puts("No"); 88 } 89 } 90 return 0; 91 }