原理介绍
本文讲的四则运算表达式包括符号: + - * / ( ) ,即带括号的加减乘除运算。
同时能够巩固对栈的理解和运用。
通常我们使用的表达式称为“中缀表达式”,特点是符号再运算数的“中间”;但是这样
的表达式让我们的计算机处理较为麻烦,波兰逻辑学家Jan Lukasiewicz就给出了另一种
表达式,称“后缀表达式”,也叫“逆波兰表达式”;
譬如给出一个中缀表达式算式 : 9 * ( 3 - 1 )
用逆波兰表达式即为 :931-*
然后运算顺序是从第一个符号开始,将其前面两个数字运算
931-* => 92* => 18
如此运算;
这样的表达式算法无需括号,这也使得计算机深深的爱上了这样的表达式-逆波兰;
逆波兰表达式的算法就像栈的操作一样:
1.遇到数字就入栈
2.遇到运算符就将栈顶两数运算然后结果入栈
因此
计算机对于后缀表达式能够更好的操作,如果是处理中缀表达式,大家可以自行简单
尝试一下,感受其中处理难度的差;
表达式转化
问题来了,对于逆波兰表达式计算机可以很好的处理,但是需要得到一个逆波兰表达
式的方法才行呀。所以我们的难点还是在于:
“如何将中缀表达式转化为后缀表达式?”【中缀==>后缀】
要解决这个问题,我们必须首先规定下每个字符的【优先级】:
右括号> 乘除 > 加减 >左括号
) 大于 */ 大于 +- 大于 (
大致的步骤如下:
1.遇到数字输出
2.遇到符号入栈(这里将入栈符号设为in,栈顶符号设为top)
i).如果空栈,入栈
ii).如果栈顶符号 优先级 不低于入栈符号
从top开始弹栈,直至优先级低于入栈符号in结束,in入栈
*注意:如果入栈符号in==右括号")",则遇到左括号"("停止弹栈;
iii).如果栈顶符号 优先级 低于入栈符号
top不弹栈,in入栈
code
void Determ(char in,string& ret,stack<char>& st) {
if (st.empty()) {
st.push(in);
return;
}
if (in == ')') {
while (st.top() != '(') {
ret += st.top();
st.pop();
}
if (!st.empty()) st.pop();
}
else if (st.top() == '*' || st.top() == '/') {
if (in == '*' || in == '/') {
while (st.top() == '*' |