九度OJ 1019 简单计算器(栈的应用)
来源:互联网 发布:js实现二级菜单导航 编辑:程序博客网 时间:2024/05/16 06:11
- 读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
原题地址:http://ac.jobdu.com/problem.php?pid=1019
题目描述:
- 输入:
- 测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
- 输出:
- 对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
- 样例输入:
1 + 24 + 2 * 5 - 7 / 110
- 样例输出:
3.0013.36
- 来源:
2006年浙江大学计算机及软件工程研究生机试真题
本题考查的是利用堆栈对表达式求值,这类问题的基本思想如下:
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 205using 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)
- 九度OJ 1019 简单计算器(栈的应用)
- 九度OJ 1019 简单计算器
- 九度oj 题目1019:简单计算器
- 九度oj-1019:简单计算器
- 九度OJ-题目1019:简单计算器
- 九度oj-1019-简单计算器
- 九度OJ 1019:简单计算器
- 九度OJ-1019-简单计算器
- 九度OJ 题目1019:简单计算器
- 九度OJ-1019简单计算器
- <九度 OJ>题目1019:简单计算器
- 九度OJ 题目1019:简单计算器
- 九度OJ 1019 简单计算器
- 【九度oj】1019简单计算器
- 九度 OJ 题目1019:简单计算器
- 九度OJ-题目1019 简单计算器
- 九度OJ题目1019:简单计算器
- 题目1019:简单计算器 九度OJ
- 文件上传org.springframework.web.multipart.MultipartException问题的解决
- “多线程下载”情形下的程序结构设计
- centos7 安装Oracle11GR2
- Guide——欢迎使用CSDN-markdown编辑器
- linux下使用yum安装mysql
- 九度OJ 1019 简单计算器(栈的应用)
- 反转排序 自我经典理解
- 关于自动化测试模型介绍
- Access Modify Change三个时间的概念及修改
- web技术栈中不可或缺的Linux技术
- maven的常用命令及配置阿里云镜像
- Qt之模态对话框和非模态对话框.
- linux下使用yum安装mysql
- [时间序列分析][2]--趋势和(季节)因子