逆波兰表达式(RPN)算法简单实现

Posted Qcer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆波兰表达式(RPN)算法简单实现相关的知识,希望对你有一定的参考价值。

算法分析:

一、预处理

给定任意四则运算的字符串表达式(中缀表达式),preDeal预先转化为对应的字符串数组,其目的在于将操作数和运算符分离。

例如给定四则运算内的中缀表达式:

String infix = "100+8*5-(10/2)*5+10.5";

字符串数组化后得:

{"100","+","8","*","5","-","(","10","/","2",")","+","10.5"}

二、中缀表达式转后缀表达式

规则:

遍历中缀表达式,

A、如果遇到操作数直接输出

B、如果遇到运算符,分情况:

B1:如果是*、/或者(这三个运算符,直接压栈

B2:如果是),则出栈直到遇到(位置。(左括号和有括号并不参与拼接后缀表达式)。

B3:如果是+或者-,先弹栈直到栈空,再讲当前的+或者-压栈。

其中情况B可以总结:

遇到右括号出栈直到匹配左括号,遇到操作符,如果其优先级高于栈顶元素,则继续压栈,否则出栈。

三、计算后缀表达式

规则:

遍历后缀表达式:

A、遇到操作数压栈

B、遇到运算符则将栈顶和次栈顶两个元素取出参与对应的运算,再将运算结结果压栈。

 

java算法实现:

  1 package agstring;
  2 import java.util.*;
  3 
  4 
  5 public class RPN {
  6     public static String[] preDeal(String infix){
  7         infix = infix.trim();
  8         int length = infix.length();
  9         ArrayList<String> infixOfArrayList = new ArrayList<String>();
 10         char currChar;
 11         int index = 0;
 12         final String regex = "\\+|-|\\*|\\/|\\(|\\)";
 13         for (int i = 0; i < length; i++) {
 14             currChar = infix.charAt(i);
 15             if(String.valueOf(currChar).matches(regex)){//运算符
 16                 if (index < i) {
 17                     infixOfArrayList.add(infix.substring(index,i));//add数字
 18                 }
 19                 infixOfArrayList.add(String.valueOf(currChar));
 20                 index = i+1;
 21             }
 22         }
 23         infixOfArrayList.add(infix.substring(index,length));
 24         return infixOfArrayList.toArray(new String[infixOfArrayList.size()]);
 25     }
 26     public static String[]  getPostfix(String infix) {
 27         String[] infixOfAry = preDeal(infix);
 28         int length = infixOfAry.length;
 29         ArrayDeque<String> stack = new ArrayDeque<String>();
 30         String currString = "";
 31         final String regex = "\\+|-|\\*|\\/|\\(|\\)";
 32         ArrayList<String> postfixOfArrayList = new ArrayList<String>();
 33         for (int i = 0; i < length; i++) {
 34             currString = infixOfAry[i];
 35             if (currString.matches(regex)) {//symbol
 36                 if (currString.matches("\\*|\\/|\\(")) {
 37                     stack.offerFirst(currString);
 38                 }else {//),+,-
 39                     String top = "";
 40                     if(currString.equals(")")){
 41                         while(!stack.isEmpty()){
 42                             top = stack.removeFirst();
 43                             if (top.equals("(")) {
 44                                 break;
 45                             }
 46                             postfixOfArrayList.add(top);
 47                         }
 48                     }else {//+ ,-
 49                         if (!stack.isEmpty()) {
 50                             top = stack.peekFirst();
 51                             if (top.equals("*") || top.equals("/")) {
 52                                 while(!stack.isEmpty()){
 53                                     postfixOfArrayList.add(stack.removeFirst());
 54                                 }
 55                             }
 56                         }
 57                         stack.offerFirst(currString);
 58                     }
 59                 }
 60             }else {//number
 61                 postfixOfArrayList.add(currString);
 62             }
 63         }
 64         while(!stack.isEmpty()){
 65             postfixOfArrayList.add(stack.removeFirst());
 66         }
 67         return postfixOfArrayList.toArray(new String[postfixOfArrayList.size()]);
 68     }
 69     public static double computePostfix(String infix){
 70         String[] postfixAry = getPostfix(infix);
 71         ArrayDeque<Double> stack = new ArrayDeque<Double>();
 72         int length = postfixAry.length;
 73         String currString = "";
 74         final String regex = "\\+|-|\\*|\\/|\\(|\\)";
 75         double operandOne,operandTwo;
 76         for (int i = 0; i < length; i++) {
 77             currString = postfixAry[i];
 78             if (currString.matches(regex)) {
 79                 operandOne = stack.removeFirst();
 80                 operandTwo = stack.removeFirst();
 81                 switch (currString.charAt(0)) {
 82                 case ‘+‘:
 83                     stack.addFirst(operandTwo + operandOne);
 84                     break;
 85                 case ‘-‘:
 86                     stack.addFirst(operandTwo - operandOne);
 87                     break;
 88                 case ‘*‘:
 89                     stack.addFirst(operandTwo * operandOne);
 90                     break;
 91                 case ‘/‘:
 92                     stack.addFirst(operandTwo / operandOne);
 93                     break;
 94                 }
 95                 
 96             }else {
 97                 stack.addFirst(Double.parseDouble(currString));
 98             }
 99         }
100         return stack.removeFirst();
101     }
102     public static void main(String[] args) {
103         // TODO Auto-generated method stub
104         try {
105             String infix = "100+8*5-(10/2)*5+10.5";
106             double result = computePostfix(infix);
107             System.out.println(result);    
108         } catch (Exception e) {
109             // TODO: handle exception
110             e.printStackTrace();
111         }
112     }
113 
114 }

 

以上是关于逆波兰表达式(RPN)算法简单实现的主要内容,如果未能解决你的问题,请参考以下文章

数据结构——逆波兰式

算法中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果

算法中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果

波兰式与逆波兰式的转换和表达式求值

粗浅看 逆波兰式算法

LeetCode 150. 逆波兰表达式求值