逆波兰表达式(后缀表达式)

来源:互联网 发布:51单片机助手 编辑:程序博客网 时间:2024/06/06 16:47

  

   逆波兰式,也叫做后缀表达式,每一运算符都置于其运算对象之后,故称为后缀表示。值得注意的是,后缀表达式没有优先级的概念,会按照运算符从左向右进行运算。这种理解这对于把普通表达式转换为后缀表达式很重要。比如下面的式子:

   a+b ---> a,b,+
   a+(b-c) ---> a,b,c,-,+
   a+(b-c)*d ---> a,b,c,-,d,*,+
   a+d*(b-c)--->a,d,b,c,-,*,+
   a=1+3 ---> a=1,3 +

 实现代码如下:

 /**     * 计算后缀表达式,操作很简单,就是入栈和出栈进行计算     * @param tokens 后缀表达式     */public static int evalRPN(String[] tokens) {int returnValue = 0;String operators = "+-*/";Stack<String> stack = new Stack<String>();for (String t : tokens) {//如果解析到的字符不是运算符就将当前的值push到栈里,if (!operators.contains(t)) {//push~stack.push(t);} else {//如果解析到的是运算符,那么就可以进行计算了//能够保证计算结果的正确性的前提是有两个保证://1、后缀表达式的特性:运算符是紧跟着操作数后面的//2、栈的特点:栈是先进后出的特点,先push进去的元素,在pop出一个元素时,取出的是最后push进去的元素,注意,pop出一个元素后,该元素就不存在栈中了//基于以上两点,可以形成基本思路:对后缀表达式进行遍历,如果遇到的不是运算符那么就push到栈中,如果遇到运算符就将前面的两个数字取出运算//由此可见,如果一个表达式的第一个运算符的前面只有一个数字,这样的表达式不应该算是后缀表达式int a = 0, b = 0;if (!stack.empty()) {a = Integer.valueOf(stack.pop());}if (!stack.empty()) {b = Integer.valueOf(stack.pop());}//当前解析到的运算符,本例中的运算符是用一个字符串表示的四种基本运算int index = operators.indexOf(t);//将计算后的值再次push到栈中switch (index) {case 0:stack.push(String.valueOf(a + b));break;case 1:stack.push(String.valueOf(b - a));break;case 2:stack.push(String.valueOf(a * b));break;case 3:stack.push(String.valueOf(b / a));break;}}}//栈顶上的元素就是累计算的结果returnValue = Integer.valueOf(stack.pop());return returnValue;}


   以上算法是摘自:http://www.programcreek.com/2012/12/leetcode-evaluate-reverse-polish-notation/ 我只加了两个if判断。

   后缀表达式,运算及其简洁,只需要通过入栈和出栈就可以完成简单运算,但是我们平时使用的都是普通表达式,因此下面来实现将普通表达式转换为后缀表达式的算法:

  

/**      * 优先级比较      * @param operator1 比较值      * @param operator2 被比较值      * @return 小于等于返回false,大于返回true      */      public static  boolean comparePrior(String operator1, String operator2) {          if("(".equals(operator2)) {              return true;          }          if ("*".equals(operator1) || "/".equals(operator1)) {              if ("+".equals(operator2) || "-".equals(operator2)) {                  return true;              }          }          return false;      }        /**      * 转为后缀表达式:      * 1、如果是"("直接压入stack栈。      * 2、如果是")",依次从stack栈弹出运算符加到数组newExpressionStrs的末尾,值到遇到"(";      * 3、如果是非括号,比较扫描到的运算符,和stack栈顶的运算符。如果扫描到的运算符优先级高于栈顶运算符则,     *   把运算符压入栈。否则的话,就依次把栈中运算符弹出加到数组newExpressionStrs的末尾,直到遇到优先级低于扫描到的运算符或栈空,     *   并且把扫描到的运算符压入栈中。就这样依次扫描,知道结束为止。如果扫描结束,栈中还有元素,则依次弹出加到数组newExpressionStrs的末尾,     *   就得到了后缀表达式。      * @param expressionStrs      * @return      */      public static String[] toSuffixExpression(String[] expressionStrs) {          //新组成的表达式          List<String> newExpressionStrs = new ArrayList<String>();          Stack<String> stack = new Stack<String>();          for (int i = 0; i < expressionStrs.length; i++) {           // 如果是左括号,则直接            if ("(".equals(expressionStrs[i])) {                stack.push(expressionStrs[i]);              } else if ("+".equals(expressionStrs[i]) || "-".equals(expressionStrs[i]) || "*".equals(expressionStrs[i]) || "/".equals(expressionStrs[i])) {                  if (!stack.empty()) {                     String s = stack.pop();                    //如果栈值优先级小于要入栈的值,则继续压入栈                      if(comparePrior(expressionStrs[i], s)) {                         stack.push(s);                      } else {                     //否则取出值                          newExpressionStrs.add(s);                      }                  }                  stack.push(expressionStrs[i]);              } else if (")".equals(expressionStrs[i])) { //如果是")",则出栈,一直到遇到"("                  while (!stack.empty()) {                      String s = stack.pop();                      if (!"(".equals(s)) {                          newExpressionStrs.add(s);                      } else {                          break;                      }                  }              } else {                  newExpressionStrs.add(expressionStrs[i]);              }          }          while (!stack.empty()) {              String s = stack.pop();              newExpressionStrs.add(s);          }          return newExpressionStrs.toArray(new String[0]);      }  


  

  

1 0