Files
python/TangDou/CSP-J/J2_2020/ZhuanTi_BiaoDaShi/1623.cpp

89 lines
2.9 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
/*
思路
1、数据处理,通过记录入度,找到入度为0的点,找到根节点
2、二元运算必须有符号右边那个式子,即根据数据构建完树后的右孩子
故在递归遍历树的时候,只要判断该节点是否有孩子,
然后返回的字符串数: 递归左子树的string值 + 该节点的string值 + 递归右子树的string值
3、如果该节点不是根节点,则在该返回值的左右两边加上括号
4、最后输出返回值
黄海总结:
1、乍一看此题,感觉无从下手,因为不知道每个点都是什么节点号!后来慢慢从测试用例1中发现,
data 都是什么 *,a,b,-,c之类,不是节点号,应该是具体的操作符,也就是值。
那节点号在哪里呢?再看一下后面的left_child,right_child,发现是
8 7
-1 -1
4 1
2 5
这个来理解一下,应该是指8号节点,7号节点,-1代表的是NULL节点,也就是到头了,是叶子。
再来仔细看一下,发现出现的数字是:1 2 4 5 6 7 8,单单缺少了一个3!
为啥缺少3呢?
因为3不是任何人的left_child,right_child,它是根!!!!,这样的话,整个图就完整了!
*/
int n;
string w[N];
int l[N], r[N], in[N];
int isleaf[N];
/*
8
* 8 7
a -1 -1
* 4 1
+ 2 5
b -1 -1
d -1 -1
- -1 6
c -1 -1
(a+b)*(c*(-d))
*/
string dfs(int u) {
// 表达式树特点:叶子节点都是真实数字,非叶子节点都是操作符
string left, right;
// if (isleaf[u]) return w[u]; // 递归终点,如果是叶子,本句话可以省略掉
// 这是因为isleaf[u]时,l[u]==-1 && r[u]==-1 ,则下面的两个分支都不会走,直接到了return那句,left,right都是空,还是返回w[u],一样的
if (l[u] != -1) {
left = dfs(l[u]); // 递归左儿子,
if (!isleaf[l[u]]) left = "(" + left + ")"; // 如果左儿子不是叶子,需要把表达式加上括号
}
if (r[u] != -1) { // 右儿子不为空
right = dfs(r[u]); // 递归右儿子
if (!isleaf[r[u]]) right = "(" + right + ")"; // 如果右儿子不是叶子,需要把表达式加上括号
}
// 返回中序遍历结果
return left + w[u] + right;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> w[i] >> l[i] >> r[i]; // data left_child right_child
if (l[i] != -1) in[l[i]]++; // 记录入度
if (r[i] != -1) in[r[i]]++; // 记录入度
if (l[i] == -1 && r[i] == -1) isleaf[i] = 1; // 叶子
}
// 找根
int root;
for (root = 1; root <= n; root++)
if (!in[root]) break; // 入度为零的是根
// 通过中序遍历,构建中缀表达式
cout << dfs(root) << endl;
return 0;
}