1、写在前面的话
前一阵子数学建模去了,很多东西都放空了,嵌入式没学、数模集被牵着走、还睡不好,调整了一周才回神。报名比赛需谨慎啊,今年的数模是真的难受。算了,回到主题,记录下逆波兰表达式,老实说,没学计算机系统结构,第一次听到这个词还是挺懵逼的,但这个东西不难理解。
数据结构和编译原理也是有相关介绍的。
01 概念
逆波兰表达式(后缀表达式):一种表示表达式的方法(J.Lukasiewicz、1929年),按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。
备注:在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,即中缀表示。
02 例子
以下是一些将正常表达式变为逆波兰表达式的例子:
正常表达式 | 逆波兰表达式 | 稍加说明 |
---|---|---|
a+b | a,b,+ | 直接按顺序 |
a+(b-c) | a,b,c,-,+ | 运算符对应后到前 |
a+(b-c)*d | a,b,c,-,d,*,+ | 先b-c处理了再按后到前 |
a+d*(b-c) | a,d,b,c,-,*,+ | 直接一步后到前 |
a=1+3 | a=1,3 + | 等号的设计形式 |
用途:将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)*(c+d)转换为ab+cd+*
优点:只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。
运算:如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
03 demo例子
使用零地址指令编写程序时,首先要把这个算数表达式转换成逆波兰表达式,结果为:ab*c+d-ef+/
PUSH A ; 把操作数a压入堆栈
PUSH B ; 把操作数b压入堆栈
MUL ; 弹出堆栈顶部的两个操作数做乘法,结果压入堆栈中
PUSH C ; 把操作数c压入堆栈
ADD ; 弹出堆栈顶部的两个操作数做加法,结果压入堆栈中
PUSH D ; 把操作数d压入堆栈
SUB ; 弹出堆栈顶部的两个操作数做减法,结果压入堆栈中
PUSH E ; 把操作数e压入堆栈
PUSH F ; 把操作数f压入堆栈
ADD ; 弹出堆栈顶部的两个操作数做加法,结果压入堆栈中,此时有堆栈中两个数
DIV ; 弹出堆栈顶部的两个操作数做除法,结果压入堆栈中
POP X ; 将压入堆栈的中数据进行释放,结果是X