后缀表达式的相关知识

一、概念

    前缀表达式 (Prefix Notation) 也称“波兰表达式”,是为了纪念了纪念其发明者波兰数学家 Jan Lukasiewicz 而命名的。前缀表达式的特点是运算符写在前面,操作数写在后面,并且不需要括号仍能被无歧义地解析。

    后缀表达式 (Postfix Notation) 也称为“逆波兰表达式”,它的特点是操作数在前,运算符在后,并且也不需要括号。

    中缀表达式 (Infix Notation) 就是我们常用的表达式,即运算符放在操作数中间的算术表达式,会用到括号。

例子:
中缀表达式: 3+(4-2)*5
前缀表达式: +3*-425
后缀表达式: 342-5*+

二、转换
  
   平时前缀用得比较少,所以只写中缀表达式转为后缀表达式的规则。
 
1、使用栈来辅助转换
(1)建立一个栈,然后从左至右的遍历中缀表达式
(2) 如果碰到了操作数,则直接将其输出,如果碰到了操作符,这个时候则需要进行优先级的比较,如果栈为空或者栈顶的操作符的优先级比当前的低,则将当前的操作符 Push 入栈,如果栈顶操作符比当前的操作符的优先级高或者相同,则 POP 操作符并输出,直到出现前一种情况为止。(减法和加法有相同的优先级,乘法和除法有相同的优先级)
(3)如果操作数输出完毕而栈还有操作符,则依次POP操作符并输出。

    需要注意的是对于括号需要另外注意一下,如果是’(’,则直接入栈,如果是)则要找到对应的’(’为止,并且当两者同时出现时则同时删除。

例如 3+(4-2)*5 执行上面的步骤如下:

第一步: 操作数3输出
         OUTPUT: 3
         STACK : NULL
第二步: 运算法"+"入栈
         OUTPUT: 3
         STACK : +
第三步: 运算符"("入栈
         OUTPUT: 3
         STACK : + (
第四步: 操作数4输出
         OUTPUT: 3 4
         STACK : + (
第五步: 运算符"-"入栈
         OUTPUT: 3 4
         STACK : + (  -
第六步: 操作数2输出
         OUTPUT: 3 4 2
         STACK : + (  -
第七步: 遇到")"符号,"-"弹出并输出,"("弹出不输出
         OUTPUT: 3 4 2  -
         STACK : + 
第八步: 遇到"*"运算符,由于"*"比"+"优先级高,所以"*"入栈
         OUTPUT: 3 4 2  -
         STACK : + *
第九步: 操作数5输出
         OUTPUT: 3 4 2  - 5
         STACK : + *
第十步: 操作数已经输出完毕,栈还非空,因此栈中的运算符依次输出
         OUTPUT: 3 4 2  - 5 * +
         STACK : NULL
至此,中缀表达式  3+(4-2)*5  转换成了后缀表达式  342-5*+

2、根据运算的先后顺序人工转换
第一步:按照运算符的优先级对所有的运算单位加括号~
        式子变成拉:(3+((4-2)*5))
第二步:转换前缀与后缀表达式
        前缀:把运算符号移动到对应的括号前面
              则变成拉:+(3*(-(42)5))
              把括号去掉:+3*-425  前缀式子出现
        后缀:把运算符号移动到对应的括号后面
              则变成拉:(3((42)-5)*)+
              把括号去掉:342-5*+  后缀式子出现
3、借助表达式树来转换
    上面介绍的两种方法一种是用来编程实现的,一种是用于人工快速转换的,已经满足平时的需要了。这里还介绍表达式树主要的目的是强调知识之间的联系。
    表达树是二叉树,表达树的叶子节点是操作数,比如常数或变量,而其他的节点为操作符。例如表达式 3+(4-2)*5的表达树为:
                                         
对该二叉树进行前序遍历可得:+3*- 425
对该二叉树进行中序遍历可得:3+(4-2)*5
对该二叉树进行后序遍历可得:342-5*+

       对比可知,对表达式树的前序遍历得到的是前缀表达式;对表达式树的中序遍历得到的是中缀表达式;对表达式树的后序遍历得到的是后缀表达式。因此可以根据表达式树而得到后缀表达式。也可以根据后缀表达式得到表达式树,方法如下:
       “我们一次一个符号地读入表达式。如果符号是操作数,那么我们就建立一个单节点树并将一个指向它的指针推入栈中。如果符号是操作符,那么我们就从栈中弹出指向两棵树T1和T2的那两个指针(T1的先弹出)并形成一颗新的树,该树的根就是操作符,它的左、右儿子分别指向T2和T1。然后将指向这棵新树的指针压入栈中。”(详见:数据结构与算法分析——C语言描述P71)

三、计算后缀表达式

    规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。这个过程跟上面一节将后缀表达式转换成表达式树基本一致。
例如计算后缀表达式 342-5*+ 的步骤如下:
第一步:3、4、2依次入栈
        STACK : 3 4 2
第二步:遇到"-"号所以2和4弹出计算4-2=2,将结果2入栈
        STACK : 3 2
第三步:5入栈
        STACK : 3 2 5
第四步:遇到"*"号所以2和5弹出计算5*2=10,将结果10入栈
        STACK : 3 10
第四步:遇到"+"号所以10和3弹出计算10+3=13,最终结果为13。
        STACK : NULL

你可能感兴趣的:(数据结构,后缀表达式,表达式树,逆波兰)