计算一个算术表达式的值。(式子中每个数都是一位数,且除法运算时整除,即3/2=1。输入数据保证每个表达式合法。)
标签:
计算一个算术表达式的值。(式子中每个数都是一位数,且除法运算时整除,即3/2=1。输入数据保证每个表达式合法。)
有多组测试样例。一个算术表达式占一行。
输出表达式的值。
1+1
2*3
2
6
分析:就是一个含有加减乘除的表达式,并且不含有括号,计算其值。明明是很简单的表达式求值,愣是让我水了几个小时,也是醉了。。。看来真是老了
表达式求值:1、先按照计算法则,给出各运算符的优先级,这个是为了比较两个相邻运算符应该先算哪一个。
2、接下来就是真正的比较计算了,总体的比较思想是开两个栈,一个用来存数字(题目比较水,只是一位的数字),一个用来存运算符。
3、从头到尾扫描一遍表达式,逐个读入数字或运算符,如果是数字,则直接压入数字栈即可;要是运算符,则要考虑以下几种情况:
1.运算符栈为空时,直接进栈即可。
2.若不为空,则比较当前运算符和运算符栈顶运算符的优先级,若栈顶的大,就代表它的优先级比较大,我们就要先把栈顶运算符弹出栈,同时从数字栈中弹出栈顶的两个数字,因为这两个数字就是运算符栈顶元素的两个操作数(这个如果不懂得话,可以手动模拟一下操作步骤,即可明白其间的关系),这点要注意,由于栈的特点,我们取出的数字顺序,是跟原来在运算符两边的位置是相反的,所以计算的时候要调过来。再把计算出的结果压入数字栈。
3.重复步骤3.2,直到当前运算符的优先级大于运算符栈顶运算符的优先级,这时,我们再把当前等待入栈的运算符入栈。
4、重复步骤2,直到表达式扫描完为止。
5、最后,运算符栈里剩的就是优先级相等的运算符了,我们只需要把它们一个一个取出来,按照顺序算出来即可。这个顺序,比上面的简单很多,每次从运算符栈顶弹出一个运算符op,再从数字栈里依次弹出两个数a,b,那么最后计算b op a的值,再将其放入数字栈中,直到运算符栈为空的时候,刚好我们的数字栈中只剩下了一个元素(因为每个运算符都是两个操作数,但是所有的都相邻排列的,所以所有的操作数恰好比运算符多1个),这个就是我们表达式的最终结果。
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <ctime> #include <stack> using namespace std; #define INF 0x7fffffff #define LL long long #define LLL(a, b) a<<b #define RRR(a, b) a>>b #define MID(a, b) a+(b-a)/2 const int maxn = 10000000 + 10; int cal(int x, int y, char p){ //计算x op y的值 if(p == '*') return x * y; else if(p == '/') return x / y; else if(p == '+') return x + y; else return x - y; } int main(){ #ifdef sxk freopen("in.txt", "r", stdin); //不用看,从文件读入用的,跟题目无关 #endif // sxk int n; int pri[300]; string s; memset(pri, 0, sizeof(pri)); //初始化优先级数组 pri['*'] = pri['/'] = 3; //设定运算符的优先级 pri['+'] = pri['-'] = 1; while(cin >> s){ //读入表达式 stack<int> num; //数字栈 stack<char> op; //运算符栈 int len = s.size(); for(int i=0; i<len; i++){ if(s[i] >= '0' && s[i] <= '9') num.push(s[i] - '0'); //是数字,直接压入数字栈 else{ //是运算符 if(!op.size()) op.push(s[i]); //运算符栈空,直接入栈 else{ while(pri[ s[i] ] <= pri[ op.top() ]){ //循环判断,把栈顶优先级不小于当前运算符优先级的运算符全部弹出栈 int x = num.top(); num.pop(); //弹出两个数字 int y = num.top(); num.pop(); char c = op.top(); op.pop(); //弹出运算符 num.push(cal(y, x, c)); //把计算结果压入数字栈 if(op.size() == 0) break; //一定要注意,不判空的话,会报Runtime Erro } op.push(s[i]); //再把当前待入栈运算符入栈 } } } while(op.size()){ //最后的计算 int x = num.top(); num.pop(); int y = num.top(); num.pop(); char c = op.top(); op.pop(); num.push(cal(y, x, c)); } printf("%d\n", num.top()); //栈顶元素,即为表达式的最终结果 } return 0; }
标签:
原文地址:http://blog.csdn.net/u013446688/article/details/42464271