问题描述
中缀表达式就是我们通常所书写的数学表达式,后缀表达式也称为逆波兰表达式,在编译程序对我们书写的程序中的表达式进行语法检查时,往往就可以通过逆波兰表达式进行。我们所要设计并实现的程序就是将中缀表示的算术表达式转换成后缀表示,例如,将中缀表达式
(A 一 (B*C 十 D)*E) / (F 十 G )
转换为后缀表示为:ABC*D十E*--FG十/
注意:为了简化编程实现,假定变量名均为单个字母,运算符只有+,-,*,/ 和^(指数运算,要注意运算符的结合性),可以处理圆括号 (),并假定输入的算术表达式正确。
要求:使用栈数据结构实现 ,输入的中缀表达式以#号结束
输入
整数N。表示下面有N个中缀表达式
N个由单个字母和运算符构成的表达式
输出
N个后缀表达式。
emmm,做题之前同学跟我说这题很难,网上CSDN有两三百行……确实体现了这个课是5学分的分量,而且也是我本科生涯之后所有课程中学分最多。
做这题需要会什么
1栈的操作(应该用C++的库会快一些
2中缀转后缀的原理
然后是用栈来实现转后缀的操作,怎么做到判断符号的大小呢
(后入栈时优先度高,先入栈时有限度低。我们可以在他们入栈时单独考虑
然后要注意的问题是^,这个图上没给
我们这里要用到auto函数
For(auto &x : str)
是利用x
生成str
中每一个值的引用,对x
的操作会影响到原容器。
我将其分为三类
1数字直接入
2除去)都归在入这一类,里面做判断,尤其特定^
3符号)属于必须出
需要两个函数
1判断是否为符号
2给符号赋值
这里消除最末尾的#有两种方法,1是if(c==’#’)braek;
高级方法是string.pop_back();
字符串被赋值之后最后一个字符就直接删
最后要注意,栈里会还剩一些没输出的,要自己清掉
#include<bits/stdc++.h>
/*
2
a+b*c-d#
a-b*(c+d)#
s.empty(); //如果栈为空则返回true, 否则返回false;
s.size(); //返回栈中元素的个数
s.top(); //返回栈顶元素, 但不删除该元素
s.pop(); //弹出栈顶元素, 但不返回其值
s.push(); //将元素压入栈顶
*/
using namespace std;
int zifu(char c){
if (c=='+'||c=='-'||c=='*'||c=='/'||c=='^'||c=='('){
return 1;}
else{
return 0;
}
}
int dengji(char c){
if(c=='('){
return 0;
}
if(c=='+'||c=='-'){
return 1;
}
if(c=='*'||c=='/'){
return 2;
}
if(c=='^'){
return 3;
}
if(c==')'){
return 4;
}
}
int main(void){
int N;
cin>> N;
while(N--){
stack<char> st;
string ans;
string m;
cin>>m;
m.pop_back();
for(auto& p : m){
if(zifu(p)==1){
if(p=='('||p=='^'){
st.push(p);
}
else if(st.empty()||dengji(st.top())<dengji(p)){
st.push(p);
}
else if(dengji(st.top())>=dengji(p)){
while(!st.empty()&&dengji(st.top())>=dengji(p)){//可能出到没元素了
ans+=st.top();
st.pop();
}
st.push(p);
}
}
else if(p==')'){
while(st.top()!='('){
ans+=st.top();
st.pop();
}
st.pop();//把(去掉
}
else{//数字
ans+=p;
}
}
while(!st.empty()){
ans+=st.top();
st.pop();
}
cout<<ans<<endl;
}
}