数据结构与波兰 逆波兰 表达式

算术表达式:前缀表达式、中缀表达式、后缀表达式相互转换

概念:三者的区别在于运算符相对于操作数的位置有所不同

之所以叫波兰式是为了纪念波兰的数理学家而设立的。

前缀表达式(波兰式) 对应于二叉树的前序遍历

前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。

中缀表达式 对应于二叉树的中序遍历

中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。

后缀表达式(逆波兰式)对应于二叉树的后序遍历

后缀表达式将运算符写在操作数之后

虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单

计算机用的比较多的是后缀表达式

运算符优先级

##一元操作符优先级比较高

转换

1. 中缀表达式转换为其他两种

方法:

  1. 首先按照运算符的优先级对所有的运算单位加括号
  2. 转前缀则将符号移动到对应括号之前
  3. 转后缀则将符号移动到对应括号之后

转换过程

中缀表达式为:a + b * c - ( d + e )

  1. 使用按照运算符的优先级对所有的运算单位加括号
    操作完成后式子变成: ( ( a + ( b * c ) ) - ( d + e ) )
  2. 中缀表达式转前缀表达式:
    1)将运算符移动到对应括号之前:- ( + ( a * ( b c ) ) + ( d e ) )
    2)去掉括号:- + a * b c + d e
    3)转换完成
  3. 中缀表达式转后缀表达式:
    1)将运算符移动到对应括号之后:( ( a ( b c ) * ) + ( d e ) + ) -
    2)去掉括号:a b c * + d e + -
    3)转换完成

2. 前缀表达式转中缀表达式

方法:

  1. 从后向前遍历前缀表达式,如果遇到运算符,将其与后面两个操作数相结合,并在外层加上括号,当做一个新的运算符
  2. 遍历完成后,将运算符移动到括号内的操作数中间。
  3. 去掉不影响运算的括号。

转换

前缀表达式为:- + a * b c + d e

  1. 从后向前遍历遇到运算符,与后面两个结合,外层套括号,当做新的运算符。操作完成后,表达式变为:( - ( + a ( * b c ) ) ( + d e ) )
  2. 将运算符移动到括号内操作数中间,操作完成后,表达式变为:( ( a + ( b * c ) ) - ( d + e ) )
  3. 去掉多余括号后,表达式变为:a + b * c - ( d + e)

3. 后缀表达式转中缀表达式

方法:

  1. 从前向后遍历后缀表达式,如果遇到运算符,将其与前面两个操作数相结合,并在外层加上括号,当做一个新的运算符
  2. 遍历完成后,将运算符移动到括号内的操作数中间。
  3. 去掉不影响运算的括号。

转换

后缀表达式为:a b c * + d e + -

  1. 从前向后遍历遇到运算符,与前面两个结合,外层套括号,当做新的运算符。操作完成后,表达式变为:( ( a ( b c * ) + ) ( d e + ) - )
  2. 将运算符移动到括号内操作数中间,操作完成后,表达式变为:( ( a + ( b * c ) ) - ( d + e ) )
  3. 去掉多余括号后,表达式变为: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/-

那怎么构造这棵表达式的树呢?

  1. 中缀表达式,选最后运算的符号作为根结点,遍历左右两部分即可。
  2. 波兰表达式,用最前面的运算符号作为根结点,碰到数字就作为根节点即可
  3. 逆波兰表达式,从底到上构造。

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 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HehuaTang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值