前言
如果你不懂栈的操作;你可以看我的钱一篇博客栈(ADT)的定义以及基本操作(使用进制转化为例)
中缀表达式
是我们在数学里平常使用的算术表达式,如 (2 + 1) * 3;
后缀表达式
不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则);如:21 + 3 ;
如何将中缀表达式转换为后缀
我们从左到有读中缀表达式,如果读到的是操作数,立刻放到后缀表达式中;如果读到操作符,不立即放入结构体中,而是将其放入一个栈(操作符栈)中;
入栈规则
- 若为 ‘(’,入栈;
- 若为 ‘)’,则依次把栈中的的运算符加入后缀表达式中,直到出现’(’,从栈中删除’(’ (并不将’('放入后缀,而是删除!) ;
- 若为 除括号外的其他运算符, 当其优先级高于除’('以外的栈顶运算符时,直接入栈。否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号为止,然后将其自身压入栈中(先出后入)。
- 当扫描的中缀表达式结束时,栈中的的所有运算符出栈;
人工转化
第一步:按照运算符的优先级对所有的运算单位加括号;
第二步:转换后缀表达式;
后缀:把运算符号移动到对应的括号后面
把括号去掉:后缀式子出现
发现没有,后缀式是不需要用括号来进行优先级的确定的。如表达式:4 3 * 5 2 - / 6 +
步骤 |
表达式 |
0 |
4 * 3 / ( 5 / 2 ) + 6 |
1 |
( ( ( 4 * 3 ) / ( 5 - 2 ) ) + 6 ) |
2 |
( ( ( 4 3 * ) / ( 5 2 - ) ) + 6 ) |
3 |
( ( ( 4 3 * ) ( 5 2 - ) / ) + 6 ) |
4 |
( ( ( 4 3 * ) ( 5 2 - ) / ) 6 + ) |
5 |
4 3 * 5 2 - / 6 + |
将以 a + b * c + ( d * e + f ) * g 为例;
转换结果为 a b c * + d e * f + g * +
- a被读入,放入后缀表达式;
- '+'被读入,放入栈;
- b被读入,放入后缀表达式;
- '*'被读入,操作符栈的栈顶元素‘+’比 ‘ * ’优先级低,所以‘ * ’进栈。
- c被读入,放入后缀表达式;
- '+'被读入,可以发现‘+’的优先级低于‘ * ’,所以我们将‘ * ’从栈中弹出并放到后缀表达式中,接着,栈中就剩下‘+’,‘+’与现在被读入的操作符优先级相同,所以我们将‘+’从栈中弹出并放到后缀表达式中,最后,将刚刚遇到的‘+’放入栈中;
- '('被读入,由于其有着最高的优先级,直接压入栈中;
- d被读入,放入后缀表达式;
操作符栈 |
后缀表达式 |
+ ( |
a b c * + d |
- '*'被读入,栈顶元素是‘(’,除非遇到右括号,否则左括号不会从栈中弹出,因此,我们将‘ * ’压入栈中;
操作符栈 |
后缀表达式 |
+ ( * |
a b c * + d |
- e被读入,放入后缀表达式;
操作符栈 |
后缀表达式 |
+ ( * |
a b c * + d e |
- '+'被读入,我们将‘ * ’弹出并放入后缀表达式,然后将‘+’压入栈中;
操作符栈 |
后缀表达式 |
+ ( + |
a b c * + d e * |
- f被读入,放入后缀表达式;
操作符栈 |
后缀表达式 |
+ ( + |
a b c * + d e * f |
- ')'被读入,我们将栈元素逐个弹出,直到遇到‘(’,最后将‘(’删除;
操作符栈 |
后缀表达式 |
+ |
a b c * + d e * f + |
- '*'被读入,将其压入栈中;
操作符栈 |
后缀表达式 |
+ * |
a b c * + d e * f + |
- g被读入,放入后缀表达式;
操作符栈 |
后缀表达式 |
+ * |
a b c * + d e * f + g |
- 现在输入为空,因此我们将,栈中的符号逐一弹出,直到表达式为空;
操作符栈 |
后缀表达式 |
|
a b c * + d e * f + g * + |
至此,转换成功;
如何计算后缀表达式的值
这里用后缀表达式 **6 5 2 3 + 8 * + 3 + ***来示例;
首先,将 6 5 2 3放入栈中:
下面读到操作符‘+’,所以讲栈顶元素 3 弹出,接着再将栈顶元素2弹出;并计算 3 + 2 = 5的值后将5压入栈中;
接着,8进栈;
现在见到操作符‘*’,弹出5和8,计算5 * 8 = 40,并将40压入栈中;
接着是‘+’号,弹出40和5,计算40 + 5 = 40,并将45压入栈中;,
接着:是3,入栈;
‘+’,弹出45和3,计算45 + 3 = 48,并将48压入栈中;,
‘*’,弹出48和6,计算48 * 6 = 288,并将288压入栈中;
最后结果是288;