题目描述
小明在学习了数据结构之后,突然想起了以前没有解决的算术表达式转化成后缀式的问题,今天他想解决一下。
因为有了数据结构的基础小明很快就解出了这个问题,但是他突然想到怎么求出算术表达式的前缀式和中缀式呢?小明很困惑。聪明的你帮他解决吧。
输入
输入一算术表达式,以\’#\’字符作为结束标志。(数据保证无空格,只有一组输入)
输出
输出该表达式转换所得到的前缀式 中缀式 后缀式。分三行输出,顺序是前缀式 中缀式 后缀式。
示例输入
a*b+(c-d/e)*f#
示例输出
+ab-c/def
a*b+c-d/e*f
ab*cde/-f*+
题解:
先找到最后一个参与运算的运算符,下面讲解如何寻找最后一个运算符,代码里面用到了一个变量p,只有当p=0的时候才考虑这个运算符,因为括号里的运算符一定不是最后一个运算的(整个表达式被括号括起来的情况后面会进行特殊处理),我们在用c1记录最右边出现的加减号,c2记录乘除号,如果括号外有加减号,他们肯定最后计算,如果没有加减号则乘除最后运算,如果括号外没有运算符则说明整个表达式被括号括起来了,我们把这一层括号去掉(改变左右边界值)再次进行递归,最后就得到了最后需要计算的运算符s[c1]它的左子树为区间[x,c1],右子树为区间[c1+1,y]。
CODE:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1000;
int lch[maxn],rch[maxn];//每个结点的左右子结点编号
char op[maxn];//排序后先序遍历字符1-nc
int nc = 0;//结点数
int build_tree(char *s, int x, int y)
{
int i, c1 = -1, c2 = -1, p = 0;
int u;
if(y-x == 1){//仅一个字符
u = ++nc;
lch[u] = rch[u] = 0;
op[u] = s[x];
return u;
}
for(i = x; i < y; i++){
switch(s[i]){
case '(': p++; break;
case ')': p--; break;
case '+': case '-': if(!p) c1 = i; break;
case '*': case '/': if(!p) c2 = i; break;
}
}
if(c1 < 0) c1 = c2;//找不到括号外的加减号,就用乘除号
if(c1 < 0) return build_tree(s, x+1, y-1);//如果括号外加减乘除号都没有,说明整个表达式被一对括号括起来了
u = ++nc;
lch[u] = build_tree(s, x, c1);
rch[u] = build_tree(s, c1+1, y);
op[u] = s[c1];
return u;
}
void preOrder(int u)
{
if(u)
{
cout << op[u];
preOrder(lch[u]);
preOrder(rch[u]);
}
}
void inOrder(int u)
{
if(u)
{
inOrder(lch[u]);
cout << op[u];
inOrder(rch[u]);
}
}
void postOrder(int u)
{
if(u)
{
postOrder(lch[u]);
postOrder(rch[u]);
cout << op[u];
}
}
int main()
{
char s[1000];
cin >> s;
int u = build_tree(s,0,strlen(s)-1);//去除#
//for(int i=1;i<=nc;i++)
//cout << op[i] ;
preOrder(u);
cout << endl;
inOrder(u);
cout << endl;
postOrder(u);
return 0;
}