描述
我们熟悉的表达式如a+b、a+b*(c+d)等都属于中缀表达式。中缀表达式就是(对于双目运算符来说)操作符在两个操作数中间:num1 operand num2。同理,后缀表达式就是操作符在两个操作数之后:num1 num2 operand。ACM队的“C小加”正在郁闷怎样把一个中缀表达式转换为后缀表达式,现在请你设计一个程序,帮助C小加把中缀表达式转换成后缀表达式。为简化问题,操作数均为个位数,操作符只有+-*/ 和小括号。
- 输入
- 第一行输入T,表示有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个表达式。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。并且输入数据不会出现不匹配现象。 - 输出
- 每组输出都单独成行,输出转换的后缀表达式。
- 样例输入
-
2 1+2 (1+2)*3+4*5
- 样例输出
-
12+ 12+3*45*+
思路:
用一个栈存放符号,用一个队列存放数(因为后缀数的顺序和中缀数的顺序一致)。判断优先级,“+,-”赋值为1,“*,/”赋值为2,“(”赋值为3,“)”赋值为0.
特别注意“(”进栈后,优先级就最低了,到时一个if()特殊对待下就行。
如果是数,就进队列;如果是符号。优先级比较,如果栈空,直接进栈,如果栈不空并且新的符号比栈顶符号优先级大,则进栈,否则说明要进行一个运算了。则进行一次部分出结果(先将队列中的数弄出来,再从栈中出符号,出符号要特别注意,分当前符号是“)”,当前符号不是“)”两种情况讨论),具体细节见代码注释。
代码:
#include<iostream>
#include<stack>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
stack<char> op;
queue<char> num;
char ch[1001];
bool is_op(char a);
int fun(char a);
int main()
{
int T,i,len;
char c;
cin>>T;
do
{
scanf("%s",ch);
len = strlen(ch);
for(i = 0 ; i < len ; ++i)
{
if(!is_op(ch[i]))//不是符号
num.push(ch[i]);
else//是符号
{
if(op.empty())
op.push(ch[i]);
else//符号栈里有符号
{
if(ch[i] != ')')//新符号不是右括号
{
if( op.top() == '(' || fun(op.top()) < fun(ch[i]) )
op.push(ch[i]);
else
{
while( !num.empty())
{
cout<<num.front(); num.pop();
}
if(!op.empty())
{
cout<<op.top(); op.pop();
}
--i;
}
}//if()不是右括号
else//新括号是右括号
{
while( !num.empty())
{
cout<<num.front(); num.pop();
}
while( !op.empty() )
{
if(op.top() != '(')
{
c = op.top();
cout<<op.top(); op.pop();
}
else
{
op.pop();//去掉那个“(”
if(!op.empty())
{
if( op.top() != '(' && fun(op.top()) > fun(c) )
{
cout<<op.top();op.pop();
break;
}
else
break;
}
}
}
}
}
}//else是符号
}//for(i)
while(!num.empty())
{
cout<<num.front(); num.pop();
}
while(!op.empty())
{
cout<<op.top(); op.pop();
}
cout<<endl;
}while(--T);
// system("pause");
return 0;
}
bool is_op(char a)
{
if(a=='+'||a=='-'||a=='*'||a=='/'||a=='('||a==')')
return true;
else
return false;
}
int fun(char a)
{
switch(a)
{
case '+':
case '-':return 1;break;
case '*':
case '/':return 2;break;
case '(':return 3;break;
default:return 0;break;
}
}