我他喵的被這題氣死好吧。(2年前的我調了3個小時,2年後調了1.5個小時)
求一箇中綴表達式的值(小學生都會好吧)
首先:計算機最喜歡的一定是後綴表達式,我們只要從頭到尾遍歷,然後碰到數字就壓入棧,碰到運算符就直接取出棧頂的2個元素直接進行計算,並將結果壓入棧。
那我們這裏要做的操作就是將中綴轉成後綴。
怎麼做呢?
1.碰到數字將他輸出
2.碰到左括號將他入棧。
3.碰到運算符只要棧頂符號的優先級不低於新符號,就不斷取出棧頂並輸出,最後把新符號入棧。
4.若是碰到右括號,就一直輸出直到碰到左括號。
#include <bits/stdc++.h>
using namespace std;
string s;
stack<char> sa;
stack<int> sb;//是int型的
int cp(char x1,char x2)//判斷x1是否>=x2
{
if(x1=='^') return 1;
if((x1=='*'||x1=='/')&&(x2!='^')) return 1;
if((x1=='+'||x1=='-')&&(x2!='^'&&x2!='*'&&x2!='/')) return 1;
return 0;
}
//優化:賦值然後直接比較
int pow(int a,int x)
{
int ans=1;
while(x)
{
if(x&1) ans=ans*a;
a=a*a;
x>>=1;
}
return ans;
}
void cal(char ch)
{
int x=sb.top();sb.pop();int y=sb.top();sb.pop();
if(ch=='+') sb.push(x+y);
if(ch=='-') sb.push(y-x);
if(ch=='*') sb.push(x*y);
if(ch=='/') sb.push(y/x);
if(ch=='^') sb.push(pow(y,x));
//x,y不要搞反了啊
}
int main()
{
cin>>s;int num=0;
if(s[0]=='-') s='0'+s;
for(int i=1;i<s.size();i++)
{
if(s[i]=='-'&&s[i-1]=='(') s=s.substr(0,i)+'0'+s.substr(i);
}
//對於負數的處理
for(int i=0;i<s.size();i++)
{
// cout<<s[i]<<".";
if(s[i]>='0'&&s[i]<='9')
{
num=0;
while(s[i]>='0'&&s[i]<='9'&&i<s.size())
{
num=num*10+(s[i]-'0');i++;
}
// printf("%d ",num);
sb.push(num);
i--;
//
}
else
{
if(s[i]=='(') sa.push(s[i]);
else if(s[i]==')')
{
char x=sa.top();
while(x!='(')
{
sa.pop();
// cout<<x<<" ";
cal(x);
x=sa.top();
}
sa.pop();
}
else
{
// if(sa.size()) 放這裏有p用啊,放while裏面
{
while(sa.size()&&cp(sa.top(),s[i]))//優先級大的先輸出
{
// cout<<sa.top()<<" ";
cal(sa.top());
sa.pop();
}
//sa.push(s[i]);
}
sa.push(s[i]);
}
}
}
while(!sa.empty()) {/*cout<<sa.top()<<" ";*/if(sa.top()!='('&&sa.top()!=')') cal(sa.top());sa.pop();}
//會有多餘括號
cout<<sb.top()<<endl;
// cout<<(2^4)<<endl;
return 0;
}
/*
2+(3*4-1)*2
*/