zoukankan      html  css  js  c++  java
  • 数据结构Java实现06----中缀表达式转换为后缀表达式

    本文主要内容:

    • 表达式的三种形式
    • 中缀表达式与后缀表达式转换算法

    一、表达式的三种形式:

    • 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3。我们从小做数学题时,一直使用的就是中缀表达式。
    • 后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则),如:2 1 + 3 *。又比如3+(6-4/2)*5=23的后缀表达式为:3642/-5*+# (#符号为结束符)
    • 前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3 。前缀表达式和后缀表达式其实是差不多的,只不过符号位置不同而已,前缀表达式不是很常见。

    二、中缀表达式转换为后缀表达式:(思路)

    1、将中缀表达式转换为后缀表达式:(步骤,有点难理解)

    (1)当读到数字直接送至输出队列中;

    (2)当读到运算符t时:

      a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;

        注:这句话不好理解,可以说成这样,从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级低的或者遇到了一个左括号就停止

      b.t进栈;

    (3)读到左括号时总是将它压入栈中;

    (4)读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号;

    (5)中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。

     

    举例:

    124b3dd7-f3b3-4110-904c-8a2b1d85dccd

    上图中,左侧的那一列为输出序列,右侧的那一列为栈。

    2、运用后缀表达式进行计算:

      (1)建立一个栈S;

      (2)从左到右读后缀表达式,读到数字就将它转换为数值压入栈S中,读到运算符则从栈中依次弹出两个数分别到Y和X,然后以“X 运算符 Y”的形式计算机出结果,再压加栈S中;

      (3)如果后缀表达式未读完,就重复上面过程,最后输出栈顶的数值则为结束。

    举例:

    3+(2-5)*6/3=-3 ,其后缀表达式为:325-6*3/+。其运算结果如下:

    45270e43-7c61-4ac2-af8f-efb437e8d742

    三、代码实现:将中缀表达式转换为后缀表达式

    • JDK  Stack类使用
    • 使用泛型

    代码实现:

    (1)StringToArithmetic.java:(中缀表达式转化为后缀表达式的工具类

      1 /**
      2  * Created by smyhvae on 2015/9/7.
      3  * 工具类:
      4  * 1、中缀表达式转化为后缀表达式
      5  * 2、给出一个算术表达式(中缀表达式),直接得到计算结果
      6  */
      7 
      8 import java.util.Stack;
      9 import java.util.regex.Pattern;
     10 
     11 public class StringToArithmetic {
     12 
     13     private StringToArithmetic() {
     14     }
     15 
     16     //方法:给出一个算术表达式(中缀表达式),得到计算结果。 例如 (5+8+10)*1,返回23
     17     public static double stringToArithmetic(String string) {
     18         return suffixToArithmetic(infixToSuffix(string));
     19     }
     20 
     21     /**
     22      * 中缀表达式转后缀表达式 只处理了+,-,*,/和括号,没有处理负号及其它运算符,也没对前缀表达式验证。
     23      * 如要处理负号,可对表达式进行预转义处理,当下面条件成立时,将负号换成单目运算符"!" infix.charAt[i]=='-'&&(
     24      * i==0||infix.charAt[i-1]=='(')
     25      * 3*6/4+3
     26      * 3+6-4           3 6 + 4 -
     27      * 3+(6-4/2)*5    3 6 4 2 / - 5 * +
     28      */
     29     //方法:中缀表达式转成后缀表达式
     30     public static String infixToSuffix(String infix) {
     31         Stack<Character> stack = new Stack<Character>();
     32         String suffix = "";
     33         int length = infix.length();
     34         for (int i = 0; i < length; i++) {
     35             Character temp;
     36             char c = infix.charAt(i);
     37             switch (c) {
     38                 // 忽略空格
     39                 case ' ':
     40                     break;
     41                 // 碰到'(',push到栈
     42                 case '(':
     43                     stack.push(c);
     44                     break;
     45                 // 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
     46                 case '+':
     47                 case '-':
     48                     while (stack.size() != 0) {
     49                         temp = stack.pop();
     50                         if (temp == '(') {
     51                             stack.push('(');
     52                             break;
     53                         }
     54                         suffix += " " + temp;
     55                     }
     56                     stack.push(c);
     57                     suffix += " ";
     58                     break;
     59                 // 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中
     60                 case '*':
     61                 case '/':
     62                     while (stack.size() != 0) {
     63                         temp = stack.pop();
     64                         if (temp == '(' || temp == '+' || temp == '-') {
     65                             stack.push(temp);
     66                             break;
     67                         } else {
     68                             suffix += " " + temp;
     69                         }
     70                     }
     71                     stack.push(c);
     72                     suffix += " ";
     73                     break;
     74                 // 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号
     75                 case ')':
     76                     while (stack.size() != 0) {
     77                         temp = stack.pop();
     78                         if (temp == '(')
     79                             break;
     80                         else
     81                             suffix += " " + temp;
     82                     }
     83                     // suffix += " ";
     84                     break;
     85                 //如果是数字,直接送至输出序列
     86                 default:
     87                     suffix += c;
     88             }
     89         }
     90 
     91         //如果栈不为空,把剩余的运算符依次弹出,送至输出序列。
     92         while (stack.size() != 0) {
     93             suffix += " " + stack.pop();
     94         }
     95         return suffix;
     96     }
     97 
     98 
     99     /**
    100      * postfix
    101      *
    102      * @return double
    103      */
    104     //方法:通过后缀表达式求出算术结果
    105     public static double suffixToArithmetic(String postfix) {
    106 
    107         Pattern pattern = Pattern.compile("\d+||(\d+\.\d+)"); //使用正则表达式 匹配数字
    108         String strings[] = postfix.split(" ");  //将字符串转化为字符串数组
    109         for (int i = 0; i < strings.length; i++)
    110             strings[i].trim();  //去掉字符串首尾的空格
    111         Stack<Double> stack = new Stack<Double>();
    112 
    113         for (int i = 0; i < strings.length; i++) {
    114 
    115             if (strings[i].equals(""))
    116                 continue;
    117 
    118             //如果是数字,则进栈
    119             if ((pattern.matcher(strings[i])).matches()) {
    120 
    121                 stack.push(Double.parseDouble(strings[i]));
    122             } else {
    123                 //如果是运算符,弹出运算数,计算结果。
    124                 double y = stack.pop();
    125                 double x = stack.pop();
    126                 stack.push(caculate(x, y, strings[i])); //将运算结果重新压入栈。
    127             }
    128         }
    129         return stack.pop(); //弹出栈顶元素就是运算最终结果。
    130 
    131     }
    132 
    133     private static double caculate(double x, double y, String simble) {
    134         if (simble.trim().equals("+"))
    135             return x + y;
    136         if (simble.trim().equals("-"))
    137             return x - y;
    138         if (simble.trim().equals("*"))
    139             return x * y;
    140         if (simble.trim().equals("/"))
    141             return x / y;
    142         return 0;
    143     }
    144 }

    (2)Test.java:(测试类)

     1 public class Test {
     2     public static void main(String[] args) {
     3 
     4         String str = "3+(2-5)*6/3";  //其后缀表达式为325-6*3/+
     5 
     6         //调用方法:中缀表达式转成后缀表达式
     7         System.out.println(StringToArithmetic.infixToSuffix(str));
     8 
     9         //调用方法:给出一个算术表达式(中缀表达式),得到计算结果
    10         System.out.println(StringToArithmetic.stringToArithmetic(str));
    11 
    12     }
    13 
    14 }

    上方代码中,第07行是根据中缀表达式算出后缀表达式。

    第10行:是给出一个中缀表达式,直接的到计算结果,其实它的步骤是:先根据中缀表达式得到后缀表达式,然后根据后缀表达式去计算结果

    运行效果:

    68bb3685-b736-4d3b-95ad-6a6981b80071

  • 相关阅读:
    494 Target Sum 目标和
    493 Reverse Pairs 翻转对
    492 Construct the Rectangle 构建矩形
    491 Increasing Subsequences 递增子序列
    488 Zuma Game 祖玛游戏
    486 Predict the Winner 预测赢家
    485 Max Consecutive Ones 最大连续1的个数
    483 Smallest Good Base
    Django Form组件
    Django Auth组件
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4790373.html
Copyright © 2011-2022 走看看