思路
表达式树非叶节点为操作符,叶节点为操作数,并且只要对其进行中序遍历就能得到表达式。
添加括号的时机:对于某个结点及其子树构成的子表达式,如果这个结点不是叶节点,就要在该子表达式两侧添加括号。
#include<string>
#include<iostream>
#include<unordered_set>
using namespace std;
struct node {
string val;
int left, right;
}table[30];
int root = 1;
string res;
bool isOperator(int pos) {
return table[pos].left != -1 || table[pos].right != -1;
}
void inorder(int cur) {
if (table[cur].left != -1) {
if (isOperator(table[cur].left)) {
res += '(';
inorder(table[cur].left);
res += ')';
}
else inorder(table[cur].left);
}
res += table[cur].val;
if (table[cur].right != -1) {
if (isOperator(table[cur].right)) {
res += '(';
inorder(table[cur].right);
res += ')';
}
else inorder(table[cur].right);
}
}
int main() {
int n;
scanf("%d", &n);
if (n == 0)
return 0;
unordered_set<int> visited;
for (int i = 1;i <= n;i++) {
cin >> table[i].val >> table[i].left >> table[i].right;
cin.get();
visited.insert(table[i].left);
visited.insert(table[i].right);
}
for (int i = 1;i <= n;i++) {
if (visited.find(i) == visited.end()) {
root = i;
break;
}
}
inorder(root);
cout << res;
}
二刷:
判断是否需要加括号时,不用判断某个结点是否操作符,只需判断它是否叶节点即可:如果不是叶节点,就加括号。
#include<iostream>
#include<string>
#include<stack>
#include<unordered_set>
using namespace std;
struct node {
string val;
int left, right;
}table[21];
string res;
void inorderTraverse(int cur) {
if (cur == -1) {
return;
}
if (table[cur].left != -1 || table[cur].right != -1) {
res += "(";
}
inorderTraverse(table[cur].left);
res += table[cur].val;
inorderTraverse(table[cur].right);
if (table[cur].left != -1 || table[cur].right != -1) {
res += ")";
}
}
int main() {
int n;
cin >> n;
int root = 1;
unordered_set<int> visited;
for (int i = 1; i <= n; i++) {
cin >> table[i].val >> table[i].left >> table[i].right;
visited.insert(table[i].left);
visited.insert(table[i].right);
}
while (visited.count(root) != 0) {
root++;
}
inorderTraverse(root);
if (res.size() > 1) { //保证只有一个字符的表达式不会被去掉
res = res.substr(1, res.size() - 2); //去掉最外层多余的括号
}
cout << res;
}
优化:
只要在中序遍历过程中记录当前深度,如果当前不是第一层且不是叶结点,就加括号。
#include<iostream>
#include<string>
#include<stack>
#include<unordered_set>
using namespace std;
struct node {
string val;
int left, right;
}table[21];
string res;
void inorderTraverse(int cur, int depth) {
if (cur == -1) {
return;
}
if ((table[cur].left != -1 || table[cur].right != -1) && depth > 1) {
res += "(";
}
inorderTraverse(table[cur].left, depth + 1);
res += table[cur].val;
inorderTraverse(table[cur].right, depth + 1);
if ((table[cur].left != -1 || table[cur].right != -1) && depth > 1) {
res += ")";
}
}
int main() {
int n;
cin >> n;
int root = 1;
unordered_set<int> visited;
for (int i = 1; i <= n; i++) {
cin >> table[i].val >> table[i].left >> table[i].right;
visited.insert(table[i].left);
visited.insert(table[i].right);
}
while (visited.count(root) != 0) {
root++;
}
inorderTraverse(root, 1);
cout << res;
}