一、题目描述
问题描述
中缀表达式就是我们通常所书写的数学表达式,后缀表达式也称为逆波兰表达式,在编译程序对我们书写的程序中的表达式进行语法检查时,往往就可以通过逆波兰表达式进行。我们所要设计并实现的程序就是将中缀表示的算术表达式转换成后缀表示,例如,将中缀表达式
(A 一 (B*C + D)*E) / (F + G )
转换为后缀表示为:ABC*D+E*--FG+/
注意:为了简化编程实现,假定变量名均为单个字母,运算符只有+,-,*,/ ,^和圆括号 (),并假定输入的算术表达式正确。
要求:使用栈数据结构实现 ,输入的中缀表达式以#号结束
输入
整数N。表示下面有N个中缀表达式
N个由单个字母和运算符构成的表达式输出
N个后缀表达式。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示
- 1↵
- (A-(B*C+D)*E)/(F+G)#↵
以文本方式显示
- ABC*D+E*-FG+/↵
1秒 64M 0 测试用例 2 以文本方式显示
- 2↵
- a+b*c-d#↵
- a-b*(c+d)#↵
以文本方式显示
- abc*+d-↵
- abcd+*-↵
1秒 64M 0
二、思路分析
一道课上讲过的题目变种罢了。
要做这道题,你需要会的有:
①知道什么是中缀表达式和后缀表达式。
②栈的基本操作。
③基本了解如何使用栈来计算普通的四则运算。
在语法方面,会调用stack的库可以让你的程序变得更加简洁美观;另外,由于不是实时计算数字结果,而是使用字母公式来替代,涉及到字符数组的操作,如果使用字符串string会方便很多。
中缀表达式计算过程如下:
(图片来自老师上课的PPT)
至于中缀转后缀的具体操作过程,其实和普通的中缀表达式的运算过程差不多。鉴于笔者懒得写也觉得自己根本表达不清楚,建议想要了解的同学还是看看网上其他的资料罢。当然读懂上面的中缀表达式算法之后靠自己想出来中缀转后缀也不是啥难事就是了。
三、代码实现
#include<bits/stdc++.h> //万能头文件
using namespace std;
//TypeDe用来判断字符的类型,1表示字母变量,0表示七种运算符
int TypeDe(char c) {
if (c=='+' || c=='-' || c=='*' || c=='/' || c=='^' || c=='(' || c==')') return 0;
else return 1;
}
//拼接
void Joint(string *v1, string v2, char opn) {
(*v1) = (*v1)+v2+opn;
return;
}
//运算符等级优先度的量化评价
int lvl(char c) {
switch (c) {
case '(': return 0; //“(”的优先级最低,这样其他运算符就可以直接进栈
case '+': case '-': return 1;
case '*': case '/': return 2;
case '^': return 3;
case ')': return 4;
}
}
//运算符之间的优先级比较
int cmp(char ctop, char cnew) {
int lvl(char);
if (ctop=='^' && cnew=='^') return 0; //特殊情况,文末会说
if ( lvl(ctop)>=lvl(cnew) ) return 1;
else return 0;
}
//主程序
int main(){
int n;
cin >> n;
int TypeDe(char);
void Joint(string*, string, char);
int lvl(char);
for (int k=0;k<n;k++) {
char c;
stack<char> op; //op是存放运算符的栈
stack<string> vrle;//vrle是存放变量或者运算结果的栈
while ( (c=getchar())!='#' ) {
if (TypeDe(c)==1) {
//如果是字母变量,直接进栈vrle即可,注意这里会经过一个char->string的过程
string cstr;
cstr = c;
vrle.push(cstr);
}
else if (op.size() && c!='(') {
char op_top;
op_top = op.top();
while ( ((op_top!='(' && c==')') || cmp(op_top,c)>0) && op.size() ) {
//如果外面的运算符优先级低于op顶部的运算符,就进行一次运算,并且弹栈一次
string s2 = vrle.top();
vrle.pop();
Joint(&vrle.top(), s2, op_top);
op.pop();
if (op.size()) op_top = op.top();
}
if (c!=')') {
op.push(c);
}
if (op.top()=='(') op.pop();
}
else {
//如果栈空或者是左括号,直接进栈
op.push(c);
}
}
//op栈内可能还有未参与运算的运算符
while (op.size()) {
char op_top;
op_top = op.top();
string s2 = vrle.top();
vrle.pop();
Joint(&vrle.top(), s2, op_top);
op.pop();
}
//输出
while (vrle.size()) {
cout << vrle.top();
vrle.pop();
}
}
return 0;
}
一个容易错的地方
A+B+C应该是为AB+C+
A^B^C应该是ABC^^