什么是中缀表达式
中缀表达式就是大家熟悉的算数表达式,例如:
(3 × (6 + (8 - 4))) ÷ 2 - (2 + 4) × 3
这个表达式由三部分组成:操作数 、运算符 、界限符
其中界限符就是括号,它决定了该表达式中各个运算符的生效顺序。这个表达式中 '8-4' 最先生效,其次是 '6+(8-4)' 中的 '+' 号生效。如果去掉了所有括号,那么各个运算符生效的顺序就会出现错误,导致最后的计算结果出错。
那么有没有一种办法不需要括号也可以让这个表达式能够被正确的计算呢?
前缀表达式(波兰表达式)
1920年,一个波兰的数学家发明了一种不需要不需要括号也能正确表达运算符生效顺序的表示法------前缀表达式(也叫波兰表达式)
在中缀表达式中,运算符放在两个操作数的中间,而前缀表达式的运算符则放在两个操作数的前面,例如:
- 中缀:a+b ------> 前缀:+ab
- 中缀:a×b ------> 前缀:×ab
再例如:
- 中缀:a+b-c ------> 前缀:-+abc
- 中缀:a+b-c×d ------> 前缀:-+ab×cd
先把 'a+b' 转换为前缀表达式 '+ab',再把 '+ab' 看作一个整体去与 c 做减法运算:'+ab'-c
因为 '+' 和 '-' 的优先级一样,所以你也可以让 'b-c'先生效,这样就可以得到另一个前缀表达式:'+a-bc'
第二个也是先算前面的加法:'+ab',然后再算后面的乘法:'×cd',再把这两个分别当作两个整体做减法运算即可
在进行中缀转后缀的运算时需要先确定各个运算符的运算顺序
接下来试着把开头提到的表达式转成前缀表达式
(3 × (6 + (8 - 4))) ÷ 2 - (2 + 4) × 3
先来看看各个运算符的运算顺序
最先生效的是 '(8-4)',所以先计算这个,可以得到 '-84'
接着是6后面的 '+' 号,得到 '+6-84'
然后是3后面的 '×' 号,得到 '×3+6-84'
接下来就轮到 '÷2' 了,把 '×3+6-84' ÷ 2,因为2在 '×3+6-84' 这个整体的右边,所以要把2放在 '×3+6-84' 的最后面,把 '÷' 放在最前面,得到 '÷×3+6-842'
后面是减号,但是减号后面有括号以及乘号,它们的优先级都比减号要高,所以先算后面的,(2+4)×3转成前缀表达式是 '×+243'
这时还有一个 '-' 号没有参与运算,所以最后一步,把前面得到的 '÷×3+6-842' 与 '×+243' 做减法运算,最后即可得到 '-÷×3+6-842×+243' 这个前缀表达式
来看看这个前缀表达式的运算符的运算顺序
是不是感觉顺序有点乱,那我们用另一个方法试试看
中缀表达式转前缀表达式的时候可以使用右边优先的方法
什么是右边优先呢,顾名思义,如果在表达式中有两个优先级相同的运算符,那么优先计算靠右的运算符
还是用这个表达式举例
(3 × (6 + (8 - 4))) ÷ 2 - (2 + 4) × 3
按照右边优先,最先生效的是 '(2+4)',即 '+24'
其次是 '×3',即 '×+243'
再往右就是 '-',因为前面有括号和乘除,所以这个减号先不进行运算,把 '×+234' 当成一个整体放到一边
然后依次是 '(8-4)',即 '-84'
'6+',即 '+6-84'
'3×',即 '×3+6-84'
'÷2',即 '÷×3+6-842'
最后就是那个 '-' 了,把 '÷×3+6-842' 与 '×+243' 做减法运算,就得到了 '-÷×3+6-842×+243'
看看这个前缀表达式运算符的运算顺序
是不是看着顺眼很多了,从右到左运算符生效的顺序与该运算符出现的顺序一致
后缀表达式(逆波兰表达式)
后缀表达式与前缀表达式相反,后缀表达式的运算符放在两个操作数的后面
- 中缀:a+b ------> 后缀:ab+
- 中缀:a+b-c ------> 后缀:ab+c-
- 中缀:a+b-c×d ------> 后缀:ab+cd×-
在进行中缀表达式转后缀表达式的时候,则依照左边优先进行运算
试试将这个表达式转为后缀表达式
(3 × (6 + (8 - 4))) ÷ 2 - (2 + 4) × 3
① 84- ② 684-+ ③ 3684-+× ④ 3684-+×2÷ ⑤ 24+
⑥ 24+3× ⑦ '3684-+×2÷' - '24+3×' ⑧ 3684-+×2÷24+3×-
再来看看这个后缀表达式运算符的运算顺序
不难看出,这个后缀表达式的运算符从左到右的运算顺序与该运算符出现的顺序一致
前缀、后缀表达式的计算
计算前缀表达式
计算前缀表达式时,从右往左依次扫描,当扫描到运算符时,将该运算符和运算符右边的两个操作数取出计算,将计算后的结果当成一个整体,放回表达式中,继续扫描下一个运算符
- ÷ × 3 + 6 - 8 4 2 × + 2 4 3
① 从右到左扫描这个前缀表达式,当扫描到第一个运算符 '+' 时停下,取出这个运算符,并取出该运算符右边的两个数 '2'、'4',把 '+' 放到两个操作数中进行运算,得到 '6', 把 '6' 放回表达式中,此时表达式变成 '- ÷ × 3 + 6 - 8 4 2 × 6 3'
② 继续往前扫描,扫描到 '×' 时,取出该运算符,并取出该运算符右边的两个操作数 '6'、'3',计算后放回表达式,表达式变成 '- ÷ × 3 + 6 - 8 4 2 18'
③ 扫描到 '-',计算后表达式为:'- ÷ × 3 + 6 4 2 18'
④ 扫描到 '+',计算后表达式为:'- ÷ × 3 10 2 18'
⑤ 扫描到 '×',计算后表达式为:'- ÷ 30 2 18'
⑥ 扫描到 '÷',计算后表达式为:'- 15 18'
⑦ 扫描到 '-', 计算后为 '-3',当运算符全部被取出时,此时表达式中只剩下最后一个数,这个数就是最后的计算结果
计算后缀表达式
后缀表达式的计算过程与前缀表达式的计算过程类似,只不过是从左往右依次扫描,然后取出该运算符左边的两个操作数进行运算
3 6 8 4 - + × 2 ÷ 2 4 + 3 × -
① 从左到右扫描这个后缀表达式,当扫描到第一个运算符 '-' 时停下,取出这个运算符,并取出该运算符左边的两个数 '8'、'4',把 '-' 放到两个操作数中进行运算,得到 '4', 把 '4' 放回表达式中,此时表达式变成 '3 6 4 + × 2 ÷ 2 4 + 3 × -'
② 继续往后扫描,扫描到 '+' 时,取出该运算符,并取出该运算符右边的两个操作数 '6'、'4',计算后放回表达式,表达式变成 '3 10 × 2 ÷ 2 4 + 3 × -'
③ 扫描到 '×',计算后表达式为:'30 2 ÷ 2 4 + 3 × -'
④ 扫描到 '÷',计算后表达式为:'15 2 4 + 3 × -'
⑤ 扫描到 '+',计算后表达式为:'15 6 3 × -'
⑥ 扫描到 '×',计算后表达式为:'15 18 -'
⑦ 扫描到 '-', 计算后为 '-3',当运算符全部被取出时,此时表达式中只剩下最后一个数,这个数就是最后的计算结果