题目:设表达式由单字母变量、双目运算符和圆括号组成(如:“(a*(b+c)-d)/e)”。试写一个算法,将一个书写正确的表达式转换为逆波兰式。
步骤思路:
(1)首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#';
(2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:
1.若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;
2.若x是运算符,则分情况讨论:
- ①若x是'(',则直接压入栈s1;
- ②若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,此时抛弃'(';
- ③若x是除'('和')'外的运算符,则再分如下情况讨论:
- ③-1若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
- ③-2若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,若x的优先级大于栈s1栈顶运算符优先级,则将x直接压入栈s1。否者,将栈s1的栈顶运算符弹出,压入栈s2中,直到栈s1的栈顶运算符优先级别低于(不包括等于)x的优先级,或栈s2的栈顶运算符为'(',此时再则将x压入栈s1;
- ③-1若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
(3)在进行完(2)后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#');
(4)完成上述步骤后,栈s2便为逆波兰式输出结果。但是栈s2应做一下逆序处理,因为此时表达式的首字符位于栈底;
代码实现:
#include <stack>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
bool compare_precedence(char a, char b);
string RPN(string expression);
int main()
{
cout <<"Please input the normal expression:" <<endl;
string expression;
cin >> expression;
string RPN_result = RPN(expression);
cout <<"The RPN of expression is: \n"<< RPN_result <<endl;
return 0;
}
string RPN(string expression){
stack<char> s1;//临时存储运算符
s1.push('#');
stack<char> s2;//输入逆波兰式
for (decltype(expression.size()) index = 0; index != expression.size(); index++){
char x = expression[index];
if((x>='a'&& x<='z') || (x>='A' && x<='Z')){
s2.push(x);
continue;
}
else if(x=='('){
s1.push(x);
continue;
}
else if(x==')'){
while(s1.top()!='('){
s2.push(s1.top());
s1.pop();
}
if(!s1.empty() && s1.top()=='(')
s1.pop();
continue;
}
else{
if(s1.top()=='('){
s1.push(x);
continue;
}
else{
while((!compare_precedence(x,s1.top())) && s1.top()!='('){
s2.push(s1.top());
s1.pop();
}
s1.push(x);
continue;
}
}
}
if(!s1.empty()){
while(s1.top()!='#'){
s2.push(s1.top());
s1.pop();
}
}
string result;
for (int index = 0; !s2.empty(); index++){
result = result + (string(1,s2.top()));
s2.pop();
}
reverse(result.begin(), result.end());
return result;
}
//比较a的优先级是否大于b,若是则返回true,否则返回false
bool compare_precedence(char a, char b){
if(b=='#')
return true;
else if(a=='*'||a=='/'||a=='%'){
if(b=='+'||b=='-')
return true;
else
return false;
}
else if(a=='+'||a=='-'){
return false;
}
else{printf("Operator compare error!"); return -1;}
}
测试:
用例 |
输出 |
结果 |
((a+b)*c-d)/h+v%e |
|
√ |
a+b/c*(d+f)-m |
|
√ |