什么是中缀表达式,什么是后缀表达式
我们一般看见的多项式计算都是中缀表达式构成的:1+2*3+4/3
类似这种,为什么说是中缀呢?因为它的计算符号都是在两个数中间的。
那么自然而然的明白了后缀表达式是一种计算符号在两个数后面的。
如123*+43/+
中缀表达式和后缀表达式有什么关系?
其实仔细你就会发现,上面给出的式子其实都是一样的,只是计算的顺序在后缀表达式中你看不懂而已。
因为我们习惯去看中缀表达式的计算。
其实他们之间是可以互相转换的。他们也可以表达同一个意思,同一个计算式子。
为什么会提出后缀表达式
这里马上就会有问题了,为什么好好的不用中缀表达式,而提出那么一个难看的后缀表达式。
首先对于我们人来说,计算的时候看到乘法和除法自然而然的就会去先计算,而对于计算机这么笨的东西来说,它不知道。
对于中缀表达式来说,计算机不能预料到后面是否会出现高阶的计算符号,是否要先进行计算,所以在计算的次序上面很有可能出错。
所以就有了后缀表达式,计算机在计算后缀表达式的时候不用担心计算的次序。那么问题就来了,如何计算一个后缀表达式的值呢?
别急,我们先来看看如何把一个中缀表达式转换成一个后缀表达式。
中缀表达式转换成后缀表达式
这里我们提前约定一下,我们的式子包含加减乘除和小括号,所有的数据我们暂时用个位数来表示,不包含次方开方和中括号。当然也不是可以,我们这边将问题尽量简单化。
1. 从左向右扫遍历表达式:
2. If 当前遍历到的字符 ch 是操作数,则打印
3. Else If 当前遍历的ch是 ‘(‘, 入栈
4. Else If 当前遍历的ch是 ‘)’, 不断弹出栈顶元素,直到栈为空或弹出’(‘
5. Else,
…….5.1 If 上一个操作符的优先级比当前操作符ch的优先级小,或栈是空的就入栈。
……. 5.2 Else, 不断弹出栈顶的操作符,并打印,直到栈为空或当前的操作符ch的优先级大于栈顶的操作符。将当前操作符入栈。
6. 重复2-6步,直到遍历完成
7. 弹出并打印栈中的剩余的操作符
代码描述
#include<cstdio> #include<iostream> #include<cstdlib> #include<string> #include<string.h> #include<stack> using namespace std; int getRank(char sign) { switch(sign) { case '+': case '-': return 1; case '*': case '/': return 2; } return -1; } int main() { int i=0; stack<char> expStack; string expression; cin>>expression; for(i=0; i<expression.length(); i++) { if(expression[i]>='0' && expression[i]<='9') { cout<<expression[i]; } else if(expression[i] == '(') { expStack.push(expression[i]); } else if(expression[i] == ')') { char top = expStack.top(); expStack.pop(); while(!expStack.empty() && top != '(') { cout<<top; top = expStack.top(); expStack.pop(); } } else { int now = getRank(expression[i]); if(expStack.empty() || now > getRank(expStack.top())) { expStack.push(expression[i]); } else { while(!expStack.empty() && now <= getRank(expStack.top())) { cout<<expStack.top(); expStack.pop(); } expStack.push(expression[i]); } } } while(!expStack.empty()) { cout<<expStack.top(); expStack.pop(); } return 0; }
后缀表达式的计算
我们现在已经能得到后缀表达式了,那么如何利用它计算。
其实很简单,首先我们观察到后缀表达式中已经没有任何括号了,所以对于我们来说计算顺序就很容易了。
从左往右读取,数字入栈,如果遇到计算符号(比如遇到一个加号),出栈两个数然后计算(比如两个数相加),然后将结果入栈。
最后在栈中的数据就为计算的结果。
思考
栈对于带有括号的计算式,四则运算等比较好用,利用栈的特性能保存一些计算等级低的,让等级高的先进行计算。
之后遇到这样的问题可以首先考虑使用栈。