零、逆波兰表示法(后缀表达式)
为了更好的解决表达式的优先运算问题,波兰逻辑学家Jan Lukasiewicz 定义了一种后缀表示法,一般称作逆波兰(Reverse Polish Notation,RPN)表示法。
例如对表达式 “12+(7-3)*2+9/3”,如果要用后缀表示法应该是:“12 7 3 - 2 * + 9 3 / +”,这样的表达式称为后缀表达式,之所以叫做后缀,是因为所有的运算符号都是在要运算数字的后面出现。显然,这里没有了括号,说明后缀表达式具有括号优先的属性,能正确处理具有括号的表达式。
一、计算后缀表达式的值
后缀表达式之所以被定义,确是有其好处(计算机处理这种表达式很方便):
例如对于 后缀表达式 12 7 3 - 2 * + 9 3 / +
规则是:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
1.初始化一个空栈,此栈用来对要运算的数字进出使用。
2.后缀表达式中前三个元素都是数字,所以 12 7 3 进栈:
3 |
7 |
12 |
3.接下来是符号‘ - ’,于是将栈顶的两个元素出栈进行运算,注意3作为减数,7作为被减数,得到结果4继续进栈。
4 |
12 |
4.接着是数字2继续进栈:
2 |
4 |
12 |
5.接下来是符号 ‘ * ’,于是将栈顶的两个元素出栈进行运算,2*4得到8,继续进栈:
8 |
12 |
6.接着是符号‘+’,于是计算12+8=20,20入栈:
20 |
7.接着连续两个数字9,3,依次进栈:
3 |
9 |
20 |
8.然后是符号‘ / ’,将9和3出栈进行运算得9/3=3,将3进栈:
3 |
20 |
9.最后是一个符号 ‘+’,于是出栈两个元素,20+3=23,23入栈:
23 |
10.后面没有符号了,23即为表达式的值,出栈。
大家可能自然会想到,如何得到后缀表达式呢?
二、中缀表达式转后缀表达式
我们平常生活中最常用的四则运算表达式一般为标准表达式,又称作中缀表达式, 例如“12+(7-3)*2+9/3”,(因为所有运算符号都在两数字中间),现在的问题就是中缀到后缀的转化。
例如 "12+(7-3)*2 + 9 / 3" - - - - - - >>>> " 12 7 3 - 2 * + 9 3 / + "
规则:
从左到右遍历中缀表达式的每个元素,如果是数字就输出作为后缀表达式的一部分 ; 如果是符号就持续判断其与栈顶(专门放符号的栈)符号的优先级,如果优先级小于等于栈顶的符号或者该符号是右括号,就将栈顶元素依次出栈并输出作为后缀表达式的一部分,并将当前符号进栈,这样下去直到结束。
注:如果是左括号‘(’,则还未配对直接进栈;若是右括号‘)’,则栈顶依次出栈并输出,直到左括号出栈为止。
1.初始化一空栈,用来对符号进出栈使用。
(空) |
2.第一个元素是数字12,于是输出12作为后缀表达式的开始(目前后缀表达式为“12”),然后接着是符号‘+’,进栈:
+ |
3.接着是符号‘(’,依然是符号,又因为是左括号还未配对,进栈:
( |
+ |
4.然后是数字7,直接输出(更新为"12 7"),接着是符号‘ - ’,因为还未到右括号,进栈:
- |
( |
+ |
5.接着是数字3,直接输出(更新为“12 7 3”),然后是右括号,这时候依次出栈直到左括号为止:
- |
( |
+ |
6.接着是符号 *,因为*的优先级大于+,于是进栈:
* |
+ |
7.接着是数字2,直接输出(更新为“12 7 3 - 2”),然后是符号+,因为+的优先级小于*,等于+,于是栈中的两个都出栈并输出(更新为“12 7 3 - 2 * +”),然后新的符号‘+’进栈:
+ |
8.接着是数字9,于是直接输出,(更新为“12 7 3 - 2 * + 9”),然后是' / ',因为' / ',优先级大于' + ',直接进栈:
/ |
+ |
9.最后一个元素是数字3,直接输出(更新为“12 7 3 - 2 * + 9 3”),最后把栈中所剩符号依次出栈并输出即可。
最后更新为 “12 7 3 - 2 * + 9 3 / +”
总结:四则运算表达式求值分两步
1.将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
2.将后缀表达式进行运算得出结果(栈用来进出运算的数字)。