中缀表达式转后缀表达式并求值

逆波兰式

这是我们一个编译原理实验课的实验题,根据给出的中缀表达式,将它转换为后缀表达式,再根据后缀表达式求值。

刚开始,根据我之前刷的LeetCode题逆波兰式求值写的博客,我直接修改了上面的代码,添加中缀表达式转后缀表达式的操作,即得出了初始版本;

初始版本代码:

import java.util.Stack;

public class RPN
{
   //中缀表达式转化为后缀表达式
   public String changeFix(String fixExpression)
   {
       Stack<Character> stack = new Stack<>();
       //后缀表达式
       String postfixExpression = "";

       char c;

       for(int i=0; i<fixExpression.length(); i++)
       {
           c = fixExpression.charAt(i);
           //字符是数字,继续读取
           if (Character.isDigit(c) || c == '.')
           {
               postfixExpression += c;
           }       
           //运算符,分支判断,将运算符压栈
           else
           {
               char top;
               if(stack.isEmpty())
               {
                   stack.push(c);
                   continue;
               }
               switch (c)
               {
                   //忽略空格,识别到'#'结束
                   case ' ':
                   case '#':
                       break;
                   case '+':
                   case '-':
                       top = stack.peek();
                       if(top=='*'||top=='/')
                       {
                           postfixExpression += stack.pop();
                           stack.push(c);
                       }else
                       {
                           stack.push(c);
                       }
                       break;
                   case '*':
                   case '/':
                       top = stack.peek();
                       if(top == '*'||top == '/')
                       {
                           postfixExpression += stack.pop();
                           stack.push(c);
                       }else
                       {
                           stack.push(c);
                       }
                       break;
                   case '(':
                       stack.push(c);
                       break;
                   case ')':
                       top = stack.pop();
                       while(top!='(')
                       {
                           postfixExpression += top;
                           top = stack.pop();
                       }
                       break;
               }
           }
       }
       //将栈内剩余的字符出栈,加到表达式末尾
       while(!stack.isEmpty())
       {
           postfixExpression += stack.pop();
       }

       return postfixExpression;
   }

   //后缀表达式求值
   public int evalRPN(String tokens)
   {
       Stack<Integer> stack = new Stack<>();

       for (int i = 0; i < tokens.length(); i++)
       {
           char ch = tokens.charAt(i);

           if (Character.isDigit(ch))
               stack.push(Integer.valueOf(ch-48));

           //读取到四则运算,则进行相关操作
           switch (ch)
           {
               case '+':
                   int num1 = stack.peek();
                   stack.pop();
                   int num2 = stack.peek();
                   stack.pop();
                   stack.push(num2 + num1);
                   break;
               case '-':
                   int num3 = stack.peek();
                   stack.pop();
                   int num4 = stack.peek();
                   stack.pop();
                   stack.push(num4 - num3);
                   break;
               case '*':
                   int num5 = stack.peek();
                   stack.pop();
                   int num6 = stack.peek();
                   stack.pop();
                   stack.push(num5 * num6);
                   break;
               case '/':
                   int num7 = stack.peek();
                   stack.pop();
                   int num8 = stack.peek();
                   stack.pop();
                   stack.push(num8 / num7);
           }

       }

       return stack.peek();
   }

   public static void main(String[] args)
   {
       RPN rpn = new RPN();

       String s1 = "1+2*(5-3)#";
       String s2 = rpn.changeFix(s1);
       int end = rpn.evalRPN(s2);

       System.out.println("中缀表达式:" + s1 + "   转换为后缀表达式为:" + s2);
       System.out.println("后缀表达式 " + s2 + " 的值为: " + end);

   }
}

运行结果:

中缀表达式:1+2 * (5-3)# 转换为后缀表达式为:1253-*+
后缀表达式 1253-*+ 的值为: 5

在初始版本中,我输入的中缀表达式是:1+2*(5-3)#,得出的结果也是正确的,但是之后我发现了问题,比如我输入的中缀表达式中有两位及以上的数字,或者是存在小数,我的程序是识别不了的,得不出正确的结果,说明初始版本还有很多需要完善的地方。

之后我查询到了正则表达式的用法,发现初始版本中存在的问题用正则表达式很容易解决,所以有了以下版本:

修改后的版本代码:

import java.util.Stack;
import java.util.regex.Pattern;

public class RPN
{
   //中缀表达式转化为后缀表达式
   public String changeFix(String fixExpression)
   {
       Stack<Character> stack = new Stack<>();

       //后缀表达式
       String postfixExpression = "";

       for(int i=0; i<fixExpression.length(); i++)
       {
           char c = fixExpression.charAt(i);
           char top;
           //运算符,分支判断,将运算符压栈
           switch (c)
           {
               //忽略空格
               case ' ':
                   break;
               case '+':
               case '-':
                   while (!stack.isEmpty())
                   {
                       top = stack.pop();
                       if (top == '(')
                       {
                           stack.push('(');
                           break;
                       }
                       postfixExpression += " " + top;
                   }
                   stack.push(c);
                   postfixExpression += " ";
                   break;
               case '*':
               case '/':
                   while (!stack.isEmpty())
                   {
                       top = stack.pop();
                       if (top == '(' || top == '+' || top == '-')
                       {
                           stack.push(top);
                           break;
                       }
                       else
                           postfixExpression += " " + top;
                   }
                   stack.push(c);
                   postfixExpression += " ";
                   break;
               case '(':
                   stack.push(c);
                   break;
               case ')':
                   while(!stack.isEmpty())
                   {
                       top = stack.pop();
                       if (top == '(')
                           break;
                       else
                           postfixExpression += " " + top;
                   }
                   break;
               default: //数字
                   postfixExpression += c;
           }
       }
       //将栈内剩余的字符出栈,加到表达式末尾
       while(!stack.isEmpty())
       {
           postfixExpression += " " + stack.pop();
       }

       return postfixExpression;
   }

   //后缀表达式求值
   public double evalRPN(String postfixExpression)
   {
       Stack<Double> stack = new Stack<>();

       /**
        * 使用正则表达式 匹配数字 可识别小数
        *
        * 正则表达式中 \d 表示数字:[0-9],  \\d 第一个\是转义字符
        */
       Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)");

       String strings[] = postfixExpression.split(" "); //将字符串转化为字符串数组

       for (int i = 0; i < strings.length; i++)
       {
           strings[i].trim();   //去掉字符串首尾的空格
       }

       for (int i = 0; i < strings.length; i++)
       {
           if ((pattern.matcher(strings[i])).matches())
           {
               stack.push(Double.parseDouble(strings[i]));
           }
           else
           {
               double d1 = stack.pop();
               double d2 = stack.pop();
               stack.push(caculate(d1, d2, strings[i]));
           }
       }

       return stack.pop();
   }

   public static double caculate(double d1, double d2, String simple)
   {
       if (simple.trim().equals("+"))
           return d1 + d2;
       if (simple.trim().equals("-"))
           return d2 - d1;
       if (simple.trim().equals("*"))
           return d1 * d2;
       if (simple.trim().equals("/"))
           return d1 / d2;
       return 0;
   }

   public static void main(String[] args)
   {
       RPN rpn = new RPN();

       String s1 = "1.0+20*(5-3)";
       String s2 = rpn.changeFix(s1);
       double end = rpn.evalRPN(s2);

       System.out.println("中缀表达式:" + s1 + "   转换为后缀表达式为:" + s2);
       System.out.println("后缀表达式 " + s2 + " 的值为: " + end);

   }
}

运行结果:

中缀表达式:1.0+20 * (5-3) 转换为后缀表达式为:1.0 20 5 3 - * +
后缀表达式 1.0 20 5 3 - * + 的值为: 41.0

可以发现成功解决了多位数和小数的识别

你可能感兴趣的:(编译原理,数据结构与算法2018)