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
");
 87             else
 88                 printf("No
");
 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
");
 95             else
 96                 printf("No
");
 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
");
104             else
105                 printf("No
");
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
");
112             else
113                 printf("No
");
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
");
120             else
121                 printf("No
");
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
");
128             else
129                 printf("No
");
130         }
131         else if (str.find("full", 0) != -1)//是不是完整二叉树
132         {
133             if (isfullTree)
134                 printf("Yes
");
135             else
136                 printf("No
");
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
",&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 }

  

原文地址:https://www.cnblogs.com/zzw1024/p/11954451.html