PAT3-06. 式の変換
2586 ワード
<pre name="code" class="cpp">#include<string>
#include<iostream>
#include<stack>
#include<sstream>
using namespace std;
stringstream ss;
string s;
int i;
bool isop(){
char c=s[i];
return c=='('||c==')'||c=='*'||c=='/'||c=='+'&&i&&s[i-1]!='('
|| c=='-'&&i&&s[i-1]!='(';
}
void printnumber(){
ss<<' ';
if(s[i]=='+')++i;
if(s[i]=='-')ss<<s[i++];
while(s[i]>='0'&&s[i]<='9'||s[i]=='.') ss<<s[i++];
}
int main(){
int op[333] {0};
op['+']=op['-']=1, op['*']=op['/']=2;
stack<char>st;
cin>>s;
while(i<s.size())
{
if(!isop()) printnumber();
else
{
char c=s[i++];
if(c==')')
{
while(!st.empty()&&st.top()!='(')
{ss<<' '<<st.top(); st.pop(); }
st.pop();
}
else
{
while(!st.empty()&&(op[c]==1&&op[st.top()]==1||
op[c]==2&&op[st.top()]==2|| op[c]==1&&op[st.top()]==2))
{ss<<' '<<st.top(); st.pop(); }
st.push(c);
}
}
}
while(!st.empty())
{ss<<' '<<st.top(); st.pop(); }
cout<<ss.str().substr(1);
return 0;
}
似たような問題は、スタックで接尾辞式を計算することです.その論理は次のとおりです.
数字は処理せず、直接数字スタックにpushします.
符号は+-,*/,()の3種類に分けられ,それぞれ対応レベル123であると仮定する.シンボルスタックのシンボル+-*/出スタックはpopの2つの数字を意味し、計算後に結果をpushをデジタルスタックに入れ、(出スタックは処理しない)pushをシンボルスタックに入れない.
現在のシンボルスタックのトップシンボルがxであると仮定し、新しいシンボルyが1つ読み出されるたびに、2つのケースに分けられる.
一、yが)の場合、yはスタックに入る必要はありません.シンボルスタックは1つまでpopしています(popに出てきて、(popをスタックから出すのも)
二、yがそうでなければ、yは必ずスタックに入る.yは必ずスタックに入るのが鍵で、y pushを直接シンボルスタックに入れるか、x popを出してy pushをシンボルスタックに入れるかのどちらかです.xyのレベルの組み合わせは9種類あり、x popを出す必要がない場合はレベル別に6種類あります.例えばx、yはそれぞれ(*または(*または+*)、または/(または+*)ですが、x popを出す必要がある場合は3種類しかありません.xyはそれぞれ1級1級(すなわち++または--)、または2級2級2級(すなわち**または/)、または2級1級(すなわち*+または*-または/-または/-)、popが出てもこのような組み合わせであれば、ずっとpopしなければなりません.計算はすべて前から後なので、以前の記号が計算(出力)できるようにできるだけ早く計算しなければなりません.
また、2つの点があります.第1の空のスタックではpopは必要ありません.第2の最後のシンボルスタックには、空になるまでpopシンボルスタックが積み上げられている可能性があります.これにより、スタックシミュレーション接尾辞式を用いて接尾辞式を計算するプロセスがシミュレートされます.ここでスタックを出る動作を出力に変更すればよい