我们平常书写的四则运算表达式属于中缀表达式,形式为"9+(3-1)*3+10/2",因为所有的运算符号都在两操作数之间,所以称为中缀表达式。我们使用中缀表达式来计算表达式的值,不过这种形式并不适合计算机求解。接下来,我们将中缀表达式转化为后缀表达式,所谓的后缀表达式就是操作符位于操作数后面的不包含括号的算数表达式,也叫做逆波兰表达式。
1)首先介绍一种人工的转化方法(http://www.cnblogs.com/MichaelYin/archive/2012/05/02/2479248.html)。以"9+(3-1)*3+10/2"为例,按照运算的规则,找出首先计算的部分,这部分包含两个操作数和一个操作符,将操作符移动到两个操作数右侧,这就完成了第一部分的转换,将这部分看作一个操作数,按照运算规则,以相同的方法转换,转换过程如下:
2)还可以利用二叉树求得后缀表达式,首先利用中缀表达式构造二叉树,数字是叶子节点,操作符为根节点。每次找到“最后计算”的运算符,作为当前根节点,运算符左侧表达式作为左节点,右侧表达式作为右节点,然后递归处理(http://www.xuebuyuan.com/388108.html)。9+(3-1)*3+10/2对应的二叉树的构造过程如下图所示:
此二叉树做后序遍历就得到了后缀表达式。对应代码:http://www.davex.pw/2016/03/21/How-to-make-a-Expression-Tree/
3)还可以利用栈来实现中缀表达式转化为后缀表达式。转化方法如下所述:
a.从左向右扫描表达式,如果是数字就输出,否则转b。
b.如果当前扫描的字符是")",则栈顶元素出栈并输出一直到栈顶元素为"(",然后删除栈顶元素"(",并不输出。
c.如果扫描的字符或者栈顶元素是“(”,扫描的字符直接入栈。即使扫描的字符是")"也不会入栈,因为如果是")",会出栈至栈顶元素是"("。
d.如果扫描字符是"+"或者"-",则一直出栈至栈顶元素为"+"或者"-"或者"("。如果最终栈顶元素是"(",则扫描操作符直接入栈,否则,弹出栈顶元素,然后扫描的操作符再入栈。
e.如果扫描的操作符是"*"或者"/",如果栈顶元素是同优先级的"*"或者"/",首先将栈顶元素出栈,然后扫描的操作符入栈。否则,直接入栈。
f.扫描完成整个表达式之后,如果栈内还有元素,则依次全部出栈。
得到后缀表达式之后,从左至右扫描得到的后缀表达式,如果是数字,直接入栈,如果是运算符,则依次弹出两个栈顶元素,最先弹出的元素是右操作数,较后弹出的是左操作数,两操作数使用操作符计算结果结果再入栈,扫描结束时,栈中只有一个元素,就是计算结果。Java中double型变量直接进行加减乘除运算,会有精度损失,所以需要使用math包下的BigDecimal进行运算。
对应的代码如下,首先是栈的定义:
1 import java.math.BigDecimal; 2 import java.util.*; 3 4 /** 5 * Created by hfz on 2016/7/30. 6 */ 7 public class Stack_Array implements Stack { 8 public static int CAPACITY=40; 9 protected int capacity; 10 protected int top=-1; 11 protected Object[] S; 12 public Stack_Array(int capacity){ 13 this.capacity=capacity; 14 S=new Object[capacity]; 15 } 16 public Stack_Array(){ 17 this(CAPACITY);//一般情况下,使用this.方法名调用自身方法,不过在构造方法里可以使用this()的形式调用其他构造函数 18 } 19 public void push(Object ele) throws ExceptionStackFull { 20 if(getSize()==CAPACITY){ 21 throw new ExceptionStackFull("栈溢出!"); 22 } 23 S[++top]=ele; 24 } 25 public Object pop() throws ExceptionStackEmpty{ 26 if(isEmpty()){ 27 throw new ExceptionStackEmpty("栈为空,不能出栈!"); 28 } 29 Object ele=S[top]; 30 S[top--]=null; 31 return ele; 32 } 33 34 public Object top() throws ExceptionStackEmpty{ 35 if(isEmpty()){ 36 throw new ExceptionStackEmpty("栈为空,没有栈顶元素!"); 37 } 38 return S[top]; 39 } 40 public boolean isEmpty(){ 41 return (top<0); 42 } 43 public int getSize(){ 44 return top+1; 45 } 46 public static void main(String [] args){ 47 String s="9 + ( 3 - 1 ) * 3 + 10 / 2"; 48 String s1="20 * ( ( 2.44 - 1.8 ) / 0.4 + 0.15 )"; 49 50 System.out.println(reversePlishNotation2(s)); 51 System.out.println(reversePlishNotation2(s1)); 52 53 }