题目大意:给出一棵二叉符号树,求出对应的中缀表达式,需要在合适的位置加括号。
中序遍历就可以得到中缀表达式的形式,问题是在哪里加括号。观察参考示例可以发现,除了根结点和叶子节点以外,遍历到中间节点时,需要先输出左括号,再向下遍历,由叶子节点返回该节点之后,需要输出右括号。因此,添加括号的位置就在中序遍历函数的开始和结束位置,同时要限定,只有当前的节点既不是整棵树的根节点,也不是叶子节点时,才可以输出左右括号。
AC代码:
#include <bits/stdc++.h>
using namespace std;
struct Node
{
string data;
int left;
int right;
Node(){};
Node(string data, int left, int right):data(data), left(left), right(right){};
};
void inOrder(int node, vector<Node> &tree, int root)
{
if(node == -1) return;
if(node != root && (tree[node].left > -1 || tree[node].right > -1)) printf("(");
inOrder(tree[node].left, tree, root);
printf("%s", tree[node].data.c_str());
inOrder(tree[node].right, tree, root);
if(node != root && (tree[node].left > -1 || tree[node].right > -1)) printf(")");
}
int main()
{
int N;
scanf("%d\n", &N);
vector<Node> tree(N+1);
vector<bool> isRoot(N+1, true);
for (int i = 1; i <= N; ++i)
{
string data;
int left, right;
cin >> data >> left >> right;
tree[i] = Node(data, left, right);
if(left > -1) isRoot[left] = false;
if(right > -1) isRoot[right] = false;
}
int root = 1;
for(root = 1; root <= N; root++)
{
if(isRoot[root]) break;
}
inOrder(root, tree, root);
}
用系统栈的思想进行非递归实现:系统指令分为访问和输出,要点在于需要实现的顺序是:当前节点非根节点且非叶子节点时,先输出左括号,再访问左孩子,再输出自身的数据,再访问右孩子,最后输出右括号。压栈时顺序要反过来。
#include <bits/stdc++.h>
using namespace std;
struct Node
{
char data[20];
int left;
int right;
};
struct Command
{
int node;
bool print;
Command(int node, bool print):node(node), print(print){};
};
vector<Node> allNodes;
void inOrder(int node, int root)
{
stack<Command> st;
st.push(Command(node, false));
while(!st.empty())
{
Command cmd = st.top();
st.pop();
if(cmd.node == -1) continue;
if(cmd.node == -2) printf("(");
else if(cmd.node == -3) printf(")");
else
{
if(cmd.print) printf("%s", allNodes[cmd.node].data);
else
{
if(cmd.node != root && (allNodes[cmd.node].left > -1 || allNodes[cmd.node].right > -1)) st.push(Command(-3, false));
st.push(Command(allNodes[cmd.node].right, false));
st.push(Command(cmd.node, true));
st.push(Command(allNodes[cmd.node].left, false));
if(cmd.node != root && (allNodes[cmd.node].left > -1 || allNodes[cmd.node].right > -1)) st.push(Command(-2, false));
}
}
}
}
int main()
{
int N;
scanf("%d", &N);
allNodes.resize(N+1);
vector<bool> isRoot(N+1, true);
for (int i = 1; i <= N; ++i)
{
scanf("%s %d %d", allNodes[i].data, &allNodes[i].left, &allNodes[i].right);
if(allNodes[i].left > -1) isRoot[allNodes[i].left] = false;
if(allNodes[i].right > -1) isRoot[allNodes[i].right] = false;
}
int root = 1;
for(root = 1; root <= N; root++)
{
if(isRoot[root]) break;
}
inOrder(root, root);
return 0;
}