算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
解题思路:
- 中序转后序。遍历表达式,当遇到运算数时,直接输出。用堆栈来存储运算符,当前运算符优先级高于栈顶运算符优先级或者堆栈为空时,将运算符压入堆栈,确保堆栈内运算符自上而下优先级是严格递减的;否则,直接输出运算符。
- 括号嵌套。括号内的运算符优先级严格高于括号外运算符优先级,为了实现这一点,需要另外建立一个堆栈来储存堆栈内运算符的优先级。首先定义+、-号的原始优先级为0,*、/号原始优先级为1。每当遇到“(”号时,当前层次优先级flag=flag+2(flag原始值为0)当遇到“)”时,flag=flag-2;当前运算符优先级等于原始优先级加上当前层次优先级,这样就能保证括号内的+ -号优先级严格高于括号外的* /号。该机制可适用于多层嵌套的括号表达式。
-
带正负号数字处理。定义变量last,表示上一个字符,初始值为任意运算符。当遇到两个连续的运算符或者“(”+运算符的组合时,表示当前运算符为运算数的符号,直接将运算符输出(不带空格)。(ps:测试点默认负号显示,加号不显示)
代码如下:
(PS:在程序测试时,每个测试点均显示格式有误,这说明输出答案是正确的,但是格式存在问题,排除最后结尾有多余空格,数字字符需要以整形输出等可能,花了一个小时都没能解决这个问题,所以只能上传这有问题的代码了)
#include <iostream>
#include <stack>
using namespace std;
int charValue(char a);
int main(){
stack<char> s;
stack<int> w;
char a;
scanf("%c",&a);
char lasta='+';
char b;
int flag=0;
while(a!='\n'){
if(a>='0'&&a<='9'||a=='.'){
printf("%c ",a);
}
else if(a=='('){
flag+=2;
s.push(a);
}
else if(a==')'){
flag-=2;
while(1){
b=s.top();
s.pop();
if(b=='(')
break;
w.pop();
printf("%c ",b);
}
}
else {
if((lasta>'9'||lasta<'0')&&lasta!=')'&&a=='-'){
printf("%c",a);
}
else{
while(!w.empty()&&charValue(a)+flag<=charValue(s.top())+w.top()) {
b=s.top();
s.pop();
w.pop();
printf("%c ",b);
}
s.push(a);
w.push(flag);
}
}
lasta=a;
scanf("%c",&a);
}
while(!s.empty()){
b=s.top();
s.pop();
w.pop();
printf("%c",b);
if(!s.empty())
printf(" ");
}
// printf("END");
return 0;
}
int charValue(char a){
int Value;
switch(a){
case '+': Value=0;break;
case '-': Value=0;break;
case '*': Value=1;break;
case '/': Value=1;
}
return Value;
}