小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”,求出的值就是密码。小明数学学得不好,还需你帮他的忙。(“/”用整数除法)
简单的说,就是输入一个算式,让你计算它。不过这个算式要考虑运算的先后顺序,也就是此题的难点了。
如样例:
【输入样例】
1+(3+2)(7^2+69)/(2)
【输出样例】
258
计算机是没有办法分清计算的先后顺序的,所以我们需要想办法让计算机理解这个算式的计算方法。
还记得小学学加减乘除时老师讲的“优先”吗?很明显优先度越高的运算符应该先进行运算,为了让计算机理解,我们不妨对每个运算符赋一个数字值来作为其优先级,(如:“+” “-”赋为1,“*” “/”赋为二,“^”就是3了)。实现也很简单,只要定义一个map就可以将其映射了(map<char , int> mp;)
现在分清了优先级,接下来该如何计算呢?
学的时候讲的就是栈这一章,所以理所当然的想到用栈,因为栈是先进后出的,所以只要将优先级较小的运算符先放进去,最后出栈计算时就会越后计算,也就达到了目的。
对于数字,只需要一个个压进另外一个栈里,需要时弹出计算而已。
另外‘(’和‘)’要注意一下,括号内部的优先级处理方法其实是一样的,只是括号本身(指“()”两个括号及其内部式子)的优先级肯定是最高的,所以在遇到‘(’和‘)’都出现时,就将其内部所以运算符都出栈运算,否则不动‘(’。
其实是一个由中缀表达式转化为后缀表达式的过程,这里可以通过样例举个栗子(糖炒的! ):
数字 | 运算符 | 备注 |
---|---|---|
1 | 1入栈 | |
1 | + | ‘+’号入栈 |
1 | +,( | ‘(’入栈 |
1,3 | +,( | 3入栈 |
1,3 | +,(,+ | ‘+’入栈,因为没有‘)’出现,所以不动‘(’,也不用弹出之前的运算符,即使这里本来应该弹出前一个‘+’ |
1,3,2 | +,(,+ | 2入栈 |
1,5 | + | “)”入栈,“()”出现,将包含在其中的“+”弹出栈并用最后两个数字作相应运算,然后压回栈内,“(”也弹出,“5”即为3 + 2 |
1,5 | +,* | “*”入栈,优先级更高,所以不用弹出“+” |
1,5 | +,*,( | “(”入栈 |
1,5,7 | +,*,( | 7入栈 |
1,5,7 | +,*,(,^ | ‘^’入栈 |
1,5,7,2 | +,*,(,^ | 2入栈 |
1,5,49 | +,*,(,+ | ‘+’优先级小于‘^’,所以将其弹出运算,7 ^ 2为49,压回栈内,然后将‘+’入栈 |
1,5, 49,6 | +,*,(,+ | 6入栈 |
1,5,49,6 | +,*,(,+ , (乘号打不出来了,尴尬) | “*”入栈 |
1,5,49,6,9 | + ,*,(,+,(还是打不出来…) | 9入栈 |
1,5,103 | +,* | “()”又出现了!,弹出“”,运算69为54,压回;弹出“+”,运算49+54为103,压回,“(”出栈 |
1,515 | +, / | “/”优先级大于“*”,所以弹出运算为515,压回,“/”入栈 |
1,515 | +,/,( | 不知道有什么用的左括号入栈 |
1,515,2 | +,/,(, | 2入栈 |
1,515,2 | +,/ | ‘)’入栈,双双弹出,迷惑性作用 |
1,257 | + | 输入结束,开始依次弹出注意在“/”,“-"运算时要反过来运算(不是a/b而是b/a) |
258 | “+”弹出,运算,结束 |
程序有点小长,而且这个是未完成品,之前的一个程序 :
#include <bits/stdc++.h>
using namespace std;
string hhh;
map<char , int> a;
int main() {
int sum , ans;
stack<char> zz;
stack<int> hz;
a['+'] = 1;
a['-'] = 1;
a['*'] = 2;
a['/'] = 2;
a['^'] = 3;
cin >> hhh;
for (int i = 0;i < hhh.size();i++) {
if (hhh[i] <= '9' && hhh[i] >= '0') {
sum = 0;
while(hhh[i] <= '9' && hhh[i] >= '0') {
sum = sum * 10 + hhh[i