经典笔试上机考题-表达式求值
相信参加过笔试面试同学应当见到过表达式求值这道题,下面列举的一道经典的考题,本文将同大家一起细细探讨一下表达式求值这一类问题的求法,希望抛砖引玉,其中有不妥的地方也请大家多多批评指正。
/* 功能:四则运算
* 输入:strExpression:字符串格式的算术表达式,如: "3+2*{1+2*[-4/(8-6)+7]}"* 返回:算术表达式的计算结果*/public static int calculate(String strExpression){/* 请实现*/return 0;}
约束:
pucExpression字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’,
‘]’,‘{’ ,‘}’。pucExpression算术表达式的有效性由调用者保证;
预备知识
- 中缀表达式
我们常见的算术表达式,3*3,它的特点是运算符在数的中间,我们称这类算术表达式为中缀表达式。中缀表达式很符合我们人类的思维习惯,但对于机器运算来讲,却不是太明朗。这是因为算术运算是有运算优先级的,先乘除,后加减;先括号内的,在括号外;相同优先级下从左到右。
5+6/2-34
它的正确理解应该是: 5 + 6/2-34=5+3-34=8-34=8-12=-4
- 后缀表达式
后缀表达式就是运算符在运算数的而后面。它有什么特点吗?我们先看个例子,还是以1)为例,将它转化为后缀表达式形式
562/+34*-
怎么理解呢? 它的解读: 从左到右依次读取,遇到数字放起来,遇到运算符就从数字里面提取两个进行运算,比如例子里面的,62/就是6/2算完后更新到数据结构立面这样数据就为53,这样继续读取+,再从数据里面取出两个运算,这样继续下去,最后数据结构里面剩余的就是最后的运算结果。 很明显这里面用到的数据结构,具有后进先出的特性,栈就有这个性质。
解法
熟悉了上面提到的两个概念后,对题目我们应该有了一个大概的解决策略了,但先别急于写代码,我们再来看看题目。
- 通过上一节分析,我们知道解决这道题可以分两步先变中缀表达式为后缀表达式再对后缀表达式求值
- 题目里面除了±*/四则运算外,还有三种不同类型的括号,别害怕,无论再多的括号类型,我们都明白一个点,他们有一个共同的特性,括号内的表达式要优先运算。可以这样理解为如果把左括号入栈的话,读到对应的右括号,那么需要将栈内左括号之后入栈的运算符全抛出来进行运算。
- 注意到运算数是有负数的,怎么判断?
先看看怎么从字符流里面把运算数给提取出来吧,顺序读取字符,直到非数字,然后将这几个字符组成的字符串转成数字。怎么判断是负数?我的方法是增加一个变量存储上次读到的字符,然后判断前一个不是数字的话,就认为这个符号-是标识负数的意思。
到此我们整个的解题过程就比较明朗了,下面将给出完整的实现代码,注意具体实现的时候并没有讲过程分为明显的两步,而是用两个栈来代替两步过程,实现一遍读取一遍运算。有喜欢的话,可以自行拆分成两步分,这样可能更好理解。
#include <iostream>
#include <stack>
using namespace std;bool compare(char v1, char v2)
{if( v2 == '(' || v2 == '[' || v2 == '{') return true;if( (v1 == '*' || v1 == '/' ) && (v2 == '+' || v2 == '-'))return true; return false;
}void caling(char c, stack<int>& q)
{int v1 = q.top();q.pop();int v2 = q.top();q.pop();switch(c){case '+':q.push(v1+v2);break;case '-':q.push(v2 -v1);break;case '*':q.push(v1*v2);break;case '/':q.push(v2/v1);break;}
}char matching(char c)
{if( c == ')') return '(';if(c == ']') return '[';return '{';
}/* 功能:四则运算
* 输入:strExpression:字符串格式的算术表达式,如: "3+2*{1+2*[-4/(8-6)+7]}"
* 返回:算术表达式的计算结果
*/
int calculate(string strExpression)
{const char* p = strExpression.c_str();stack<char> s;stack<int> q;char last = ' ';string num;while(*p != '\0' ){switch(*p){case '(':case '[':case '{':s.push(*p);break;case ')': case ']': case '}':while(s.top() != matching(*p)){char c = s.top();s.pop();caling(c, q); }s.pop(); break;case '-':if(isdigit(last) == 0 && last != ')' && last != ']' && last != '}'){p++;int v = *p - '0';v = 0-v; q.push(v);break;}if( s.empty() ) s.push(*p);else if( compare(*p, s.top())){s.push(*p);}else{while(s.size() >0 && !compare(*p, s.top())){char c = s.top();s.pop();caling(c, q);}s.push(*p);} break;case '+': case '*':case '/':if( s.empty() ) s.push(*p);else if( compare(*p, s.top())){s.push(*p);}else{while( s.size() >0 && !compare(*p, s.top())){char c = s.top();s.pop();caling(c, q);}s.push(*p);}break; default:num.clear();while(isdigit(*p) != 0){last = *p;num.append(string(1,*p++));}q.push(std::atoi(num.c_str()));continue; }last = *p;++p; } while(!s.empty()){char c = s.top();s.pop();caling(c, q); }return q.top();
}int main()
{string exp;while(cin>>exp){cout<<calculate(exp)<<endl;}return 0;
}
经典笔试上机考题-表达式求值相关推荐
- 【经典算法】-算术表达式求值
算术表达式求值 中缀表达式 我们平时写的计算式的式子一般是这样子 格式:"操作数1 操作符 操作数2"12 * (3 + 4) - 6 + 8 / 2; // 中缀表达式 中缀表达 ...
- 使用栈解决的一类经典问题:表达式转换及求值;中缀表达式;前缀表达式,后缀表达式,中缀转前缀;中缀转后缀;后缀表达式求值;波兰式,逆波兰式
文章目录 背景知识 表达式转换问题(考研经典) 一:手工转换 (1)中缀转前缀和中缀转后缀 (2)前缀转中缀和后缀转中缀 二:用栈实现表达式转换 (1)中缀转后缀 (2)中缀转前缀 表达式计算问题(使 ...
- 九、表达式求值(1)
九.表达式求值(1) 文章目录 九.表达式求值(1) 题目描述 解题思路 上机代码 题目描述 背景: 我们的教材中已经介绍了表达式求值的算法,现在我们将该算法的功能进行扩展,要求可以处理的运算符包括: ...
- 通过一道面试题来看 C++ 语言中的表达式求值
2019独角兽企业重金招聘Python工程师标准>>> 题目一: int a = 10 ,b = 6 ; cout << a + b << " ...
- leetcode 282. Expression Add Operators | 282. 给表达式添加运算符(中缀表达式求值)
题目 https://leetcode.com/problems/expression-add-operators/description/ 题解 中缀表达式求值问题,参考:leetcode 227. ...
- leetcode 227. Basic Calculator II | 227. 基本计算器 II(中缀表达式求值)
题目 https://leetcode.com/problems/basic-calculator-ii/ 题解 这道题是 中缀表达式求值 的简化版(因为没有左右括号运算),不过输入的形式有两个处理起 ...
- 表达式求值问题数据结构课程设计
完整代码在最后~~ 1 需求分析 1.1 问题描述 表达式求值是程序设计语言编译中的一个最基本问题,就是将一个表达式转化为逆波兰表达式并求值.具体要求是以字符序列的形式从终端输入语法正确的.不含变量的 ...
- 栈的应用——表达式求值
概要 表达式求值问题可以说是一个经典问题.具体思路就是首先把输入的中缀表达式转换为后缀表达式,然后再根据后缀表达式进行计算求值. 中缀表达式转换为后缀表达式 首先我们设定运算符在进栈前与进栈后的优先级 ...
- c/c++ 表达式求值
表达式求值 [问题描述] 一个算术表达式是由操作数(operand).运算符(operator)和界限符(delimiter)组成的.假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括 ...
最新文章
- 在linux下部署安装Tomact并运行javaWeb工程
- python3基础教程廖雪峰云-学习廖雪峰Python3教程的pytho
- Sublime text 3 汉化教程
- Win64 驱动内核编程-16.WFP网络监控驱动(防火墙)
- html用css画多边形,Sass绘制多边形_Preprocessor, Sass, SCSS, clip-path, CSS处理器, 会员专栏 教程_W3cplus...
- 封装js千分位加逗号和删除逗号
- JavaScript函数绑定
- mysql decode语句_MySQL复制问题的分析
- 输出空格隔开换行_VB编程(六)数据输出 Print 及相关方法
- Windwos8.1下配置PHP环境
- 安信可BT-02 Mesh组网的AT指令集
- 6自由度机械臂建模与仿真
- 华为atn950b指导手册_全新原包装华为ATN950B 整机 传输设备
- Bootstrap导航栏示例
- win0如何添加计算机用户,Win10系统如何添加来宾账户 win10添加来宾账户的方法
- EGo1下板_数码管动态显示
- NC23053月月查华华的手机
- 计算机工程与网络学术会议,2015第五届计算机工程与网络国际学术会议
- 在anaconda环境中添加本地下载好的包
- 系统学习金融数据挖掘 之爬虫技术基础(附源代码)(网页结构基础)