郁闷的C小加(三)
2016-07-10 09:01
204 查看
郁闷的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
分析:
做过了表达式计算的人应该都会这一题。不管是要求输出前缀表达式,还是输出后缀表达式或者是计算,都是一个思想就是先将表达式转化为表达式树,然后前缀表达式就是先序遍历这棵树,计算和后缀表达式就是后序遍历这棵树。
关于表达式树的建立,核心思想是,每次找到最后计算的运算符,然后递归即可。(有了这个思想,建树函数应该就很简单了)。
AC代码:
时间限制: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
分析:
做过了表达式计算的人应该都会这一题。不管是要求输出前缀表达式,还是输出后缀表达式或者是计算,都是一个思想就是先将表达式转化为表达式树,然后前缀表达式就是先序遍历这棵树,计算和后缀表达式就是后序遍历这棵树。
关于表达式树的建立,核心思想是,每次找到最后计算的运算符,然后递归即可。(有了这个思想,建树函数应该就很简单了)。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #include <string> #include <cstdlib> const int maxn=10005; char s[maxn]; int lch[maxn],rch[maxn]; string cp[maxn]; double dp[maxn]; char op[maxn]; int nc=0; string change1(int x,int y)//将字符串转换为ttring { string s1; for(int i=x;i<y;i++) s1=s1+s[i]; return s1; } double change2(int x,int y)//将字符串转换为double { int i; double a = 0; for(i=x;i<y;i++) { if(s[i]=='.') break; } for(int j=i-1,k=1;j>=x;j--,k*=10) { a+=(s[j]-'0')*k; } for(int j=i+1,k=10;j<y;j++,k*=10) { a+=(double)(s[j]-'0')/(double)k; } return a; } int build_tree(int x,int y)//建表达式树 { int i,u,c1=-1,c2=-1,p=0; int k; for(k=x;k<y;k++) { if((s[k]>'9' ||s[k]<'0') && s[k]!='.') break; } if(k>=y)//若全部为数字或小数点 { u=++nc; cp[u]=change1(x,y); dp[u]=change2(x,y); lch[u]=rch[u]=0; return u; } for(i=x;i<y;i++) { switch(s[i]) { case '(': p++;break; case ')': p--;break; case '+': case '-': if(!p) c1 = i;break; case '*': case '/': if(!p) c2 = i;break; } } if(c1<0) c1 = c2; if(c1<0) return build_tree(x+1,y-1); u = ++nc; op[u]=s[c1]; lch[u]=build_tree(x,c1); rch[u]=build_tree(c1+1,y); return u; } void cac1(int root)//后缀表达式 { if(!lch[root]) cout<<cp[root]<<" "; if(lch[root]) cac1(lch[root]); if(rch[root]) cac1(rch[root]); if(op[root]) printf("%c ",op[root]); } double cac2(int root)//计算 { double a,b,t; if(!lch[root]) return dp[root]; if(lch[root]) a=cac2(lch[root]); if(rch[root]) b=cac2(rch[root]); switch(op[root]) { case '+' : t=a+b;break; case '-' : t=a-b;break; case '*' : t=a*b;break; case '/' : t=a/b;break; } return t; } void cac3(int root)//前缀表达式 { if(op[root]) printf("%c ",op[root]); else cout<<cp[root]<<" "; if(lch[root]) cac3(lch[root]); if(rch[root]) cac3(rch[root]); } int main() { int len,root,t; scanf("%d",&t); while(t--) { scanf("%s",s); len = strlen(s); root = build_tree(0,len-1); cac3(root); printf("=\n"); cac1(root); printf("=\n"); printf("%.2lf\n\n",cac2(root)); } return 0; }
相关文章推荐
- centos7重启apache、nginx、mysql、php-fpm命令
- python 获取 中国证券网 的公告
- Java单元测试(Junit+Mock+代码覆盖率)
- Fedora 23如何安装LAMP服务器
- HDU 4987(概率dp)
- html网页中显示浏览器标题栏小图标
- Mock方法介绍
- SQL Server对文件访问的权限
- lseek详解
- 图文详解mybatis+postgresql平台搭建步骤
- java代码中调用js
- 虚拟机网络不通:
- 一些 Android 重要知识点解析整理
- The Mathematics of Machine Learning
- Mini-project #6 - Blackjack
- ubuntu命令行的路径太长 如何缩短显示?
- 合纵连横
- Android am 指令的使用
- 设置status bar字体颜色的优化方案
- Virtualbox中如何实现主机(Win8.1)与虚机(Ubuntu 14.04)之间传输文件