Loading

树的遍历 || P1087 [NOIP2004 普及组] FBI 树

 

 

首先树的遍历分为三种,分别是先序中序和后序(根左右,左根右,左右根):

 1 struct TreeNode {
 2     int l, r, fa;
 3 } a[N];
 4 void dfs(int u) {
 5     cout << a[u] << ' ';
 6     if (a[u].l) 
 7         dfs(a[u].l);
 8     if (a[i].r)
 9         dfs(a[u].r);
10 }
Preorder

注意dfs时候如果想要递归的处理问题,可以从极端情况也就是递归到树的最后一层的时候来想,此题为例,可以不用建树一直递归输出,但是到了最后一层的时候需要返回特定值:

 1 #include <bits/stdc++.h>
 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 3 using namespace std;
 4 using i64 = long long;
 5 using ui64 = unsigned long long;
 6 //#define endl '\n';
 7 const string YES = "Yes";
 8 const string NO = "No";
 9 const int N = 1000010;
10 char find(string s) {
11     if (s.size() > 1) {
12         cout << find(s.substr(0, s.size() / 2));
13         cout << find(s.substr(s.size() / 2, s.size() / 2));
14     }
15     if ((int)s.find('1') >= 0 && (int)s.find('0') >= 0) return 'F';
16     if ((int)s.find('1') >= 0 && (int)s.find('0') < 0) return 'I';
17     return 'B';
18 }
19 
20 int main() {
21     gogo;
22     int n;
23     string s;
24     cin >> n >> s;
25     
26     cout << find(s) << endl;
27     //cout << s.substr(s.size() / 2, s.size() / 2);
28 }
View Code

 

 

补充2 : 

题解转自luogu评论区:

首先,一点基本常识,给你一个后序遍历,那么最后一个就是根(如ABCD,则根为D)。

因为题目求先序,意味着要不断找根。

那么我们来看这道题方法:(示例)

中序ACGDBHZKX,后序CDGAHXKZB,首先可找到主根B;

那么我们找到中序遍历中的B,由这种遍历的性质,可将中序遍历分为ACGD和HZKX两棵子树,

那么对应可找到后序遍历CDGA和HXKZ(从头找即可)

从而问题就变成求1.中序遍历ACGD,后序遍历CDGA的树 2.中序遍历HZKX,后序遍历HXKZ的树;

接着递归,按照原先方法,找到1.子根A,再分为两棵子树2.子根Z,再分为两棵子树。

就按这样一直做下去(先输出根,再递归);

模板概括为step1:找到根并输出

step2:将中序,后序各分为左右两棵子树;

step3:递归,重复step1,2;

 
 1 #include <bits/stdc++.h>
 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 3 using namespace std;
 4 using i64 = long long;
 5 using ui64 = unsigned long long;
 6 //#define endl '\n';
 7 const string YES = "Yes";
 8 const string NO = "No";
 9 
10 void dfs(string inorder, string postorder) {
11     if (inorder.size() > 0) {
12         cout << postorder.back();
13         int origin = inorder.find(postorder.back());
14         dfs(inorder.substr(0, origin), postorder.substr(0, origin));
15         dfs(inorder.substr(origin + 1), postorder.substr(origin, inorder.size() - origin - 1));
16     }
17 }
18 
19 int main() {
20     gogo;
21     string inorder, postorder;
22     cin >> inorder >> postorder;
23     dfs(inorder, postorder);
24 }
View Code

 

 补充3 : 

 

 

 1 #include <bits/stdc++.h>
 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 3 using namespace std;
 4 using i64 = long long;
 5 using ui64 = unsigned long long;
 6 //#define endl '\n';
 7 const string YES = "Yes";
 8 const string NO = "No";
 9 
10 int a[30][3];
11 int n;
12 void dfs(char x) {
13     if (x != '*') {
14         cout << x;
15         for (int i = 0;i < n;i ++) 
16             if (a[i][0] == x) 
17                 dfs(a[i][1]), dfs(a[i][2]);
18     }
19     return;
20 }
21 
22 int main() {
23     gogo;
24     cin >> n;
25     for (int i = 0;i < n;i ++) {
26         string s;
27         cin >> s;
28         a[i][0] = s[0], a[i][1] = s[1], a[i][2] = s[2];
29     }
30     dfs(a[0][0]);
31 }
View Code

 

 

 

 补充3 :

 

 

 

规律就是先序和后序发生不同的地方只存在于一个父节点只有一个儿子,那么答案就是2 ^ 个数次方。

如何找一个父节点只有一个儿子呢,就是如果一个节点只有一个儿子,那么这棵树的先序遍历到这个点的时候这个点的下一个一定是左儿子,同时这棵树的后序遍历到这个点的时候这个点的前一个是右儿子,那么如果这两个点相等则说明这个父节点只有一个儿子。

 1 #include <bits/stdc++.h>
 2 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 3 using namespace std;
 4 using i64 = long long;
 5 using ui64 = unsigned long long;
 6 //#define endl '\n';
 7 const string YES = "Yes";
 8 const string NO = "No";
 9 
10 
11 int main() {
12     gogo;
13     string a, b;
14     cin >> a >> b;
15     int len = a.size();
16     int ans = 0;
17     for (int i = 0;i < len - 1;i ++)
18         for (int j = 1;j < len;j ++) 
19             if (a[i] == b[j] && a[i + 1] == b[j - 1]) 
20                 ans ++;
21     cout << (1 << ans) << endl;
22 }
View Code

 

posted @ 2023-02-13 16:40  KakaDBL  阅读(134)  评论(0)    收藏  举报