算法中,算术表达式求值(前缀、中缀、后缀)(笔记小结)

基本理解

前缀、中缀、后缀是根据运算符与操作数的相对位置来划分的。
三种表达式其实就是算术表达式的三种写法,以 3+4-5为例:
①、前缀表达式(波兰式):操作符在操作数的前面,比如 +-543
②、中缀表达式:操作符在操作数的中间,这也是人类最容易识别的算术表达式 3+4-5
③、后缀表达式(逆波兰式):操作符在操作数的后面,比如 34+5-
中缀表达式是人最容易识别的,但是计算机不容易识别,计算机容易识别的是前缀表达式和后缀表达式,将中缀表达式转换为前缀表达式或者后缀表达式之后,计算机能很快计算出表达式的值
详解:直接转换法/表达式树

注意:运算符优先级 低 -> 高( + - * / %)。+和-也有优先级,不过对运算结果(表达式可能不同)无影响,在此忽略了

中缀表达式转化为前缀表达式

1,算法描述

(1)首先构造一个运算符栈S1和一个储存中间结果的栈S2。
(2)从右至左扫描中缀表达式
(3)如果是操作数时,将其压入S2。
(4)如果是运算符,则与S1栈顶元素比较优先级:
a) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
b) 否则,若该运算符优先级比栈顶运算符的较高或相等,也将运算符压入S1;
c) 否则,将S1栈顶的运算符弹出并压入到S2中,再与S1中新的栈顶运算符相比较
(5)遇到括号时:
a) 如果是右括号“)”,则直接压入S1;
b) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号 丢弃;
(6)重复步骤(2)至(5),直到表达式的最左边;
(7)若表达式扫描完,将S1中剩余的运算符依次出栈并压入S2;
(8)依次将S2中的元素出栈,结果即为对应的前缀表达式。

2,实例

将中缀表达式3+5*(2+6)-1转化为前缀表达式:最后依次将S2中的元素出栈得:-+3*5+261

3,用前缀表达式的求值

对于一个前缀表达式的求值而言,需要使用一个栈S
(1)从右至左扫描表达式
(2)如果是操作数,则将其入栈S
(3)如果是运算符,则将栈S出栈2次,将出栈的两个数作相应的运算(注意前后顺序,先出栈的在左边),然后把得到的结果入栈S。
(4)一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。

4,前缀表达式的计算机求值

  1. 从右至左扫描表达式
  2. 遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈
  3. 重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
    示例: 计算前缀表达式的值:- + 1 × + 2 3 4 5
    1)从右至左扫描,将5,4,3,2压入堆栈;
    2)遇到+运算符,弹出2和3(2为栈顶元素,3为次顶元素),计算2+3的值,得到5,将5压入栈;
    3)遇到×运算符,弹出5和4,计算5×4的值,得到20,将20压入栈;
    4)遇到1,将1压入栈;
    5)遇到+运算符,弹出1和20,计算1+20的值,得到21,将21压入栈;
    6)遇到-运算符,弹出21和5,计算21-5的值,得到16为最终结果
    可以看到,用计算机计算前缀表达式是非常容易的,不像计算后缀表达式需要使用正则匹配

中缀表达式转化为后缀表达式

1,算法描述

(1)首先构造一个运算符栈S1和一个储存中间结果的栈或线性表S2。
(2)从左至右扫描中缀表达式
(3)如果是操作数时,将其压入S2。
(4)如果是运算符,则与S1栈顶元素比较优先级:
a) 如果S1为空,或栈顶运算符为右括号“(”,则直接将此运算符入栈;
b) 否则,若该运算符优先级比栈顶运算符的较高或相等,也将运算符压入S1;
c) 否则,将S1栈顶的运算符弹出并压入到S2中,再与S1中新的栈顶运算符相比较
(5)遇到括号时:
a) 如果是左括号“(”,则直接压入S1;
b) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
(6)重复步骤(2)至(5),直到表达式的最右边;
(7)若表达式扫描完,将S1中剩余的运算符依次出栈并压入S2;
(8)从左往右依次读取S2中的元素,即为对应的后缀表达式。

2,实例

和转化前缀表达式的区别是最开始扫描和最后读取方向不同3+5*(2+6)-1转换为后缀表达式3 5 2 6 + * + 1 -

3,用后缀表达式的求值

   对于一个前缀表达式的求值而言,需要使用一个栈S
   (1)从左至右扫描表达式
   (2)如果是操作数,则将其入栈S
   (3)如果是运算符,则将栈S出栈2次,将出栈的两个数作相应的运算(注意前后顺序,后出栈的在左边),然后把得到的结果入栈S。
   (4)一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。

4, 后缀表达式的计算机求值

与前缀表达式类似,只是顺序是从左至右:

  1. 从左至右扫描表达式
  2. 遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素op 栈顶元素 ),并将结果入栈
  3. 重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
    示例:计算后缀表达式的值:1 2 3 + 4 × + 5 -
    1)从左至右扫描,将1,2,3压入栈;
    2)遇到+运算符,3和2弹出,计算2+3的值,得到5,将5压入栈;
    3)遇到4,将4压入栈
    4)遇到×运算符,弹出4和5,计算5×4的值,得到20,将20压入栈;
    5)遇到+运算符,弹出20和1,计算1+20的值,得到21,将21压入栈;
    6)遇到5,将5压入栈;
    7)遇到-运算符,弹出5和21,计算21-5的值,得到16为最终结果

总结
• 前缀表达式和后缀表达式计算的时候都是从一个方向扫描表达式,遇到数字压入栈,遇到运算符弹出栈顶的两个数进行运算并将结果入栈,重复知道结束
• 前缀和后缀表达式已经内在地包含运算顺序,因此不用括号来确定优先级


参考文献

最全 概念,完整代码
分步代码
详细代码:前缀表达式转换为后缀表达式

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值