nyoj 题目409 郁闷的C小加(三)
2016-08-21 17:25
190 查看
郁闷的C小加(三)
时间限制:1000 ms | 内存限制:65535 KB难度:4
描述 聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考“郁闷的C小加(一)”),C小加很高兴。但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值。即先把表达式转换为前缀和后缀表达式,再求值。这时又要考虑操作数是小数和多位数的情况。
输入第一行输入一个整数T,共有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数并且小于1000000。
数据保证除数不会为0。输出对于每组测试数据输出结果包括三行,先输出转换后的前缀和后缀表达式,再输出计算结果,结果保留两位小数。样例输入
2 1+2= (19+21)*3-4/5=
样例输出
+ 1 2 = 1 2 + = 3.00 - * + 19 21 3 / 4 5 = 19 21 + 3 * 4 5 / - = 119.20
上传者苗栋栋解法:
前缀表达式:
(1) 初始化一个栈:运算符栈pq和两个个字符串str(反向字符串),tmp(前缀表达式);
(2) 将中缀表达式反向,遍历字符串;
(3) 遇到操作数时,加到存储前缀表达的字符串中;
(4) 遇到运算符时,比较其与pq栈顶运算符的优先级:
(4-1) 如果pq.top()=‘#’,或栈顶运算符为右括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入pq;
(4-3) 否则,将pq栈顶的运算符弹出并加入tmp中,再次转到(4-1)与pq中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是右括号“(”,则直接压入pq;
(5-2) 如果是左括号“)”,则依次弹出pq栈顶的运算符,并加到tmp中,直到遇到右括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将pq中剩余的运算符依次弹出并加到tmp中;
(8) 输出tmp,结果即为中缀表达式对应的前缀表达式。
后缀表达式:
同上!
不同的是不需要将中缀表达式反向,还有最关键的是(4-2)步: 否则,若优先级比栈顶运算符的较高,也将运算符压入pq;
(4-3) 否则,将pq栈顶的运算符弹出并加入tmp中,再次转到(4-1)与pq中新的栈顶运算符相比较;
然后就可以算出后缀表达式了!
#include<bits/stdc++.h> using namespace std; int flag; string str; int cmp(char ch) { switch(ch) { case '+': case '-':return 1; case '*': case '/':return 2; default:return 0; } } void revers(string ss) { int len=ss.size(); for(int i=len-2;i>=0;i--) { if(ss[i]==')') str+='('; else if(ss[i]=='(') str+=')'; else str+=ss[i]; } str+='='; } int change(string st) { int i=0,len=st.size(); string tmp; stack<char>pq; pq.push('#'); while(i<len-1) { if(st[i]=='(') { pq.push(st[i]); i++; } else if(st[i]==')') { while(pq.top()!='(') { tmp+=pq.top(); pq.pop(); tmp+=' '; } pq.pop(); i++; } else if(st[i]=='+'||st[i]=='-'||st[i]=='*'||st[i]=='/') { if(flag==0) { while(cmp(pq.top())>cmp(st[i])) { tmp+=pq.top(); tmp+=' '; pq.pop(); } pq.push(st[i]); i++; } else { while(cmp(pq.top())>=cmp(st[i])) { tmp+=pq.top(); tmp+=' '; pq.pop(); } pq.push(st[i]); i++; } } else { while(st[i]>='0'&&st[i]<='9'||st[i]=='.') { tmp+=st[i]; i++; } tmp+=' '; } } while(pq.top()!='#') { tmp+=pq.top(); pq.pop(); tmp+=' '; } if(flag==0) { tmp.erase(tmp.size()-1,1); reverse(tmp.begin(),tmp.end()); tmp+=" ="; cout<<tmp<<"\n"; } else { string str1=tmp,buf; char a[100005]; tmp+='='; cout<<tmp<<"\n"; stack<double>qp; stringstream ss(str1); while(ss>>buf) { if(isdigit(buf[0])) { int i; double num; for(i=0;i<buf.size();i++) a[i]=buf[i]; a[i]='\0'; num=atof(a); qp.push(num); } else { double x=qp.top(); qp.pop(); double y=qp.top(); qp.pop(); if(buf=="+") qp.push(x+y); else if(buf=="-") qp.push(y-x); else if(buf=="*") qp.push(x*y); else qp.push(y/x); } } printf("%.2lf\n",qp.top()); } flag=1; } int main() { int T; cin>>T; while(T--) { flag=0; str.clear(); string s; cin>>s; revers(s); change(str); change(s); } return 0; }
相关文章推荐
- 南阳 oj 郁闷的c小加(三) 题目409
- NYOJ 409 郁闷的C小加(三)
- NYOJ 409 郁闷的C小加(三)
- nyoj-409 郁闷的C小加(三) (表达式求值,中缀式转前缀式,中缀式转后缀式)
- 中缀式转后缀表达式 -NYOJ 题目267郁闷的C小加(二)
- nyoj 409——郁闷的C小加(三)——————【中缀式化前缀后缀并求值】
- NYOJ 409 郁闷的C小加(三)
- 郁闷的C小加(三)(nyoj 409)
- NYOJ 257 郁闷的C小加(一)
- NYOJ 267 郁闷的C小加(二)
- NYOJ 267 郁闷的C小加(二)
- nyoj 257 郁闷的C小加(一)
- NYOJ 题目236 心急的C小加(贪心)
- nyoj_257 郁闷的c小加
- NYOJ 35 表达式求值 or 267 郁闷的C小加(二)
- NYOJ 题目236 心急的C小加
- NYOJ XYNUYOJ 郁闷的c小加(一)(数据结构)
- NYOJ - 郁闷的C小加(一)
- NYOJ-267 郁闷的C小加(二)
- nyoj-257 郁闷的C小加(一) 前缀表达式变后缀