米兔原名:空城少女已无心
首先给大家说一下什么是后缀表达式,这个题我看大家很多都是用双栈去一步一步枚举,其实对于表达式求值,后缀表达式是一个通解,我简单的描述一下怎么把原式转为后缀表达式。
如果遇到数字,就输出
如果遇到左括号,左括号入栈
如果遇到右括号,就不断地输出栈顶元素,直到遇到左括号,然后左括号也出栈
如果是算式符号(比如+-*/),那么就不断的比较新元素和栈顶元素的优先级,如果栈顶元素的优先级大于等于新元素,则输出
直到栈顶元素小于新元素的优先级
然后跑完整个字符串,再把栈中剩下的符号一次输出即可
然后我们可以求出后缀表达式,利用后缀表达式去计算表达式的结果。
代码如下,俩个都可以过题有很详细的解释。
#include<bits/stdc++.h>
using namespace std;
string s;
struct node{
int type,num;
char op;
}now;
vector<node>vec;
stack<char>st;
int solves()
{
stack<int>q;
int num;
for(int i=0;i<vec.size();i++)
{
if(vec[i].type==0)
{
q.push(vec[i].num);
}
else
{
if(vec[i].op=='+')
{
num = q.top();q.pop();num=q.top()+num;q.pop();q.push(num);
}
if(vec[i].op=='-')
{
num= q.top();q.pop();num=q.top()-num;q.pop();q.push(num);
}
if(vec[i].op=='*')
{
num= q.top();q.pop();num=q.top()*num;q.pop();q.push(num);
}
if(vec[i].op=='/')
{
num= q.top();q.pop();num=q.top()/num;q.pop();q.push(num);
}
}
}
return q.top();
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>s;
for(int i=0;i<s.size();i++)
{
if(isdigit(s[i]))
{
int num = s[i]-'0';
while(i<s.size()&&isdigit(s[i+1]))
{
i++;num=(num*10)+s[i]-'0';
}
now.type = 0;now.num=num;
vec.push_back(now);
}
if(s[i]=='(') st.push(s[i]);
if(s[i]==')')
{
while(st.top()!='(')
{
now.type=1;now.op=st.top();
st.pop();
vec.push_back(now);
}
st.pop();
}
if(s[i]=='+'||s[i]=='-')
{
while(!st.empty()&&st.top()!='(')
{
now.type=1;now.op=st.top();
st.pop();
vec.push_back(now);
}
st.push(s[i]);
}
if(s[i]=='*'||s[i]=='/')
{
while(!st.empty()&&(st.top()=='*'||st.top()=='/'))
{
now.type=1;now.op=st.top();
st.pop();
vec.push_back(now);
}
st.push(s[i]);
}
}
while(!st.empty())
{
now.type=1;now.op=st.top();
st.pop();
vec.push_back(now);
}
cout<<solves()<<endl;
return 0;
}
附带注释
#include<bits/stdc++.h>
using namespace std;
struct node{
int type,num;//type的0表示数字,1表示符号 num用来存数字
char sign;//用来存符号
}now;
vector<node>vec;//存后缀表达式
stack<char> st;
void get_RPN(string &s)
{
for(int i=0;i<s.size();i++){
if(isdigit(s[i])){//如果是字符,读取数字并存入表达式vec
int num=s[i]-'0';
while(i+1<s.size() && isdigit(s[i+1])){
i++;num=num*10+(s[i]-'0');
}
now.type=0;now.num=num;//类型为0(数字),存入num值
vec.push_back(now);
}else if(s[i]=='('){//如果是左括号,则把左括号压入栈
st.push('(');
}else if(s[i]==')'){//如果是右括号,则把栈顶直到左括号的符号都存入表达式
while(st.top()!='('){
now.type=1;now.sign=st.top();//类型为1(符号),存入sign
vec.push_back(now);
st.pop();
}
st.pop();//左括号出栈
}else if(s[i]=='*' || s[i]=='/'){//如果是乘除,则把栈顶高于和等于新符号(乘除)优先级的都输出到表达式,直到栈顶的优先级低于新符号
while(!st.empty() && (st.top()=='*' || st.top()=='/')){
now.type=1;now.sign=st.top();//类型为1(符号),存入sign
vec.push_back(now);
st.pop();
}
st.push(s[i]);//把新符号压入栈
}else if(s[i]=='+' || s[i]=='-'){//如果是加减,则把栈顶高于和等于新符号(加减)优先级的都输出到表达式,知道栈顶的优先级低于新符号
while(!st.empty() && st.top()!='('){
now.type=1;now.sign=st.top();//类型为1(符号),存入sign
vec.push_back(now);
st.pop();
}
st.push(s[i]);//把新符号压入栈
}
}
while(!st.empty()){//将剩下的字符依次输出到表达式
now.type=1;now.sign=st.top();
vec.push_back(now);
st.pop();
}
}
int get_value()
{
int num;
stack<int>st;
for(int i=0;i<vec.size();i++){
if(vec[i].type==0){
st.push(vec[i].num);
}else{
if(vec[i].sign=='+'){
num=st.top();st.pop();num=st.top()+num;st.pop();st.push(num);
}
if(vec[i].sign=='-'){
num=st.top();st.pop();num=st.top()-num;st.pop();st.push(num);
}
if(vec[i].sign=='*'){
num=st.top();st.pop();num=st.top()*num;st.pop();st.push(num);
}
if(vec[i].sign=='/'){
num=st.top();st.pop();num=st.top()/num;st.pop();st.push(num);
}
}
}
return st.top();
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
string s;
cin>>s;
get_RPN(s);
for(int i=0;i<vec.size();i++){
if(vec[i].type==0){
cout<<vec[i].num<<" ";
}else{
cout<<vec[i].sign<<" ";
}
}
cout<<endl;
cout<<get_value()<<endl;
return 0;
}