九度OJ 1019 简单计算器(栈的应用)
-
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
原题地址:http://ac.jobdu.com/problem.php?pid=1019
题目描述:
- 输入:
-
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
- 输出:
-
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
- 样例输入:
-
1 + 2 4 + 2 * 5 - 7 / 11 0
- 样例输出:
-
3.00 13.36
-
来源:
本题考查的是利用堆栈对表达式求值,这类问题的基本思想如下:
1.设立两个堆栈,一个用来存放运算符,一个用来存放操作数。
2.从左到右遍历字符串,如果遍历到运算符,则将其与运算符栈顶元素进行比较,若新运算符的优先级大于(严格大于!后面会解释)栈顶运算符,或者栈为空,则将新运算符压入栈。
3.如果新运算符的优先级小于等于栈顶运算符,则弹出栈顶运算符,再从数字栈中弹出两个数字做对应的运算,计算的结果压入数字栈,重复第三步,直到满足新运算符的优先级大于栈顶运算符。
4.遍历到数字直接入栈。遍历到字符串结束则将剩余符号栈中的运算符依次计算直到清空。
值得注意的点:
√计算结果可能是浮点数,涉及计算的结果都要声明为double型。
√一行中只有0时输入结束,意味着这一行的字符串为"0\0",不能只根据第一个符号为0就退出,比如01 + 2是允许的。
√遍历当前元素时,需要判断是符号还是数字,是数字则只需要改变函数的传参IsOp,是数字则要读入之后可能紧接着的数字(一般都不是一位数),返回这个整数。
√ 当前指向运算符的情况下,根据上述基本思想的规则,比较栈顶运算符和新运算符的优先级。注意!由于本题不存在括号,入栈新运算符的优先级必须严格大于栈顶运算符,比如栈顶是/号,来了一个*号,如果直接把*号进栈而不弹出/号,那么之后的遍历中,会导致/优先计算,比如会出现3/3*2*2=0.25的情况,而实际上应该3/3先做计算。(就算设置除法优先级优高于乘法也不能取>=,会存在3/3/6 = 6的问题,所以必须严格大于才能入栈!)
AC代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <ctype.h> #include <stack> #define MAXLEN 205 using namespace std; char str[MAXLEN]; stack<char> op; stack<double> num; int get_priority(char c) //定义四则运算的优先级 { if (c == '+' || c == '-') //加减法同级 return 1; if (c == '*' || c == '/') //乘除法同级 return 2; else return 0; } double JudgeOpNum(bool &IsOp, int &index) { if(!isdigit(str[index])) //当前字符是运算符 { IsOp = true; return -1; } else //当前字符是数字,取出这个整数 { IsOp = false; double tmp = 0; while (str[index] != '\0' && str[index] != ' ') { tmp = tmp*10 + (str[index]-'0'); index++; //返回时的index指向空格或'\0' } return tmp; } } void Calculate() //取出num栈顶的两个数做op栈顶运算,结果压入num栈 { char c = op.top(); op.pop(); double r = num.top(); num.pop(); double l = num.top(); num.pop(); double tmp = 0; if (c == '+') tmp = l+r; else if (c == '-') tmp = l-r; else if (c == '*') tmp = l*r; else tmp = l/r; num.push(tmp); } double ClearStack() //清空符号栈和数字栈 { while (!op.empty()) Calculate(); double res = num.top(); num.pop(); return res; } int main() { while(gets(str)) { if(str[0] == '0' && str[1] == '\0') //只有0 break; int index = 0; //当前操作的下标 bool IsOp = false; while (1) { if (str[index] == ' ') index++; //跳过空格 if (str[index] == '\0') //表达式已经处理完毕,直接计算出结果 { double result = ClearStack(); printf("%.2f\n",result); break; } double ret_num = JudgeOpNum(IsOp, index); //判断当前元素是符号还是数字 if (IsOp == false) //当前指向的数字入栈 { num.push((double)ret_num); } else //当前指向运算符 { //如果符号栈空或者新符号优先级大于栈顶符号(必须是>,不能是>=,否则会出现3/3*2*2=0.25的情况) if (op.empty() || get_priority(str[index]) > get_priority(op.top()) ) op.push(str[index]); else //新符号优先级小于栈顶符号 { while (!op.empty() && get_priority(str[index]) <= get_priority(op.top())) //重复直到高优先级运算完(保证栈不空) Calculate(); op.push(str[index]); //新运算符入栈 } index += 2; //跳掉空格 } } memset(str, 0, MAXLEN); } return 0; }
内存占用:1524Kb 耗时:0ms算法复杂度: O(n)

浙公网安备 33010602011771号