算术表达式:前缀表达式、中缀表达式、后缀表达式相互转换
概念:三者的区别在于运算符相对于操作数的位置有所不同
之所以叫波兰式是为了纪念波兰的数理学家而设立的。
前缀表达式(波兰式) 对应于二叉树的前序遍历
前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。
中缀表达式 对应于二叉树的中序遍历
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
后缀表达式(逆波兰式)对应于二叉树的后序遍历
后缀表达式将运算符写在操作数之后
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。
计算机用的比较多的是后缀表达式
运算符优先级
##一元操作符优先级比较高
转换
1. 中缀表达式转换为其他两种
方法:
- 首先按照运算符的优先级对所有的运算单位加括号
- 转前缀则将符号移动到对应括号之前
- 转后缀则将符号移动到对应括号之后
转换过程
中缀表达式为:a + b * c - ( d + e )
- 使用按照运算符的优先级对所有的运算单位加括号
操作完成后式子变成:( ( a + ( b * c ) ) - ( d + e ) )
- 中缀表达式转前缀表达式:
1)将运算符移动到对应括号之前:- ( + ( a * ( b c ) ) + ( d e ) )
2)去掉括号:- + a * b c + d e
3)转换完成 - 中缀表达式转后缀表达式:
1)将运算符移动到对应括号之后:( ( a ( b c ) * ) + ( d e ) + ) -
2)去掉括号:a b c * + d e + -
3)转换完成
2. 前缀表达式转中缀表达式
方法:
从后向前
遍历前缀表达式,如果遇到运算符,将其与后面两个操作数
相结合,并在外层加上括号
,当做一个新的运算符
。- 遍历完成后,将运算符移动到括号内的操作数中间。
- 去掉不影响运算的括号。
转换
前缀表达式为:- + a * b c + d e
- 从后向前遍历遇到运算符,与后面两个结合,外层套括号,当做新的运算符。操作完成后,表达式变为:
( - ( + a ( * b c ) ) ( + d e ) )
- 将运算符移动到括号内操作数中间,操作完成后,表达式变为:
( ( a + ( b * c ) ) - ( d + e ) )
- 去掉多余括号后,表达式变为:
a + b * c - ( d + e)
3. 后缀表达式转中缀表达式
方法:
从前向后
遍历后缀表达式,如果遇到运算符,将其与前面两个操作数
相结合,并在外层加上括号
,当做一个新的运算符
。- 遍历完成后,将运算符移动到括号内的操作数中间。
- 去掉不影响运算的括号。
转换
后缀表达式为:a b c * + d e + -
- 从前向后遍历遇到运算符,与前面两个结合,外层套括号,当做新的运算符。操作完成后,表达式变为:
( ( a ( b c * ) + ) ( d e + ) - )
- 将运算符移动到括号内操作数中间,操作完成后,表达式变为:
( ( a + ( b * c ) ) - ( d + e ) )
- 去掉多余括号后,表达式变为:
a + b * c - ( d + e)
后缀表达式计算:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
例如后缀表达式“3 4 + 5 × 6 -”:
从左至右扫描,将3和4压入堆栈;
遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
将5入栈;
接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
将6入栈;
最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
为什么要设计后缀表达式,有什么好处?
便于用栈实现计算,而且不需要表示运算符优先级的括号。
下图是用表达式a*(b+c)-e/f
构造的二叉树。
中序遍历,就是日常用的表达式写法。对于加法和减法需要加括号。
用前序遍历,对应前缀表达式:-*a+bc/ef
用后序遍历,对应后缀表达式:abc+*ef/-
那怎么构造这棵表达式的树呢?
- 中缀表达式,选最后运算的符号作为根结点,遍历左右两部分即可。
- 波兰表达式,用最前面的运算符号作为根结点,碰到数字就作为根节点即可。
- 逆波兰表达式,从底到上构造。
2. 编程
3. 作业
1、
【CSP 2020 提高组第一轮 q12】表达式 a*(b+c)-d
的后缀表达形式为( )。
A. abc*+d- B. -+*abcd C. abcd*+- D. abc+*d-
2、
【NOIP 2018 提高组初赛 q06】表达式 a * d - b * c 的前缀形式是( )。
A. a d * b c * -
B. - * a d * b c
C. a * d - b * c
D. - * * a d b c
3、
【NOIP 2017 提高组初赛 q07】表达式 a * (b + c) * d 的后缀形式是( )。
A. a b c d * + * B. a b c + * d *
C. a * b c + * d D. b + c * a * d
4、
【NOIP 2016 提高组初赛 q06】表达式 a*(b+c)-d 的后缀表达形式为( )。
A. abcd*+- B. abc+*d-
C. abc*+d- D. -+*abcd
5、
【NOIP 2010 提高组初赛 q07】前缀表达式“+ 3 * 2 + 5 12 ” 的值是( )。
A. 23 B. 25 C. 37 D. 65
6、
【NOIP 2009 提高组初赛 q06】表达式a*(b+c)-d的后缀表达式是:
A. abcd*+- B. abc+*d-
C. abc*+d- D. -+*abcd
7、
【NOIP 2017 普及组初赛 q12】表达式 a * (b + c) * d 的后缀形式是( )。
A. a b c d * + * B. a b c + * d *
C. a * b c + * d D. b + c * a * d
8、
【NOIP 2010 普及组初赛 q09】前缀表达式+ 3 * 2 + 5 12
的值是( )。
A. 23 B. 25 C. 37 D. 65
9、
【NOIP 2009 普及组初赛 q13】表达式a*(b+c)-d
的后缀表达式是:
A. abcd*+-
B. abc+*d-
C. abc*+d-
D. -+*abcd
答案解析:
1.d
((a*(b+c))-d)
((a*bc+)-d)
(abc+*-d)
abc+*d-
2. b
((a*d)-(b*c))
((*ad)-(*bc))
-((*ad)-(*bc))
-*ad*bc
3. b 同7
((a*(b+c))*d)
abc+*d*
4. b 同1 同9
5 同8
前缀表达式“+3*2+5 12
等价:3+2*(5+12)
值为:37
6. b 同1