逆波兰表达式

最近在做一个知识产权的项目,被知识产权各种复杂的收费方式搞得烦死。于是想写一个通用的费用计算方式,操作人员可以在后台为每个国家各种不同的知识产权产品设定价格计算公式,系统调用公式即可算出结果,这样也方便以后增加其他国家的知识产权产品,方便设定价格。

主要面临的难点有:

不同国家的知识产权收费项目不一致,最多的有多达一百项收费,少的也有十多项,因此收费公式不能写死,应能够容纳任意数目的操作数,任意数目的操作符。

于是想到了逆波兰表达式,逆波兰表达式只需要简单的入栈和出栈操作就可以解决我所面临的难题。

废话不多说,直接上代码,一看便知:

package reversePolishDemo;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 逆波兰表达式测试
 */
public class ReversePolish {    
     private final static ConcurrentHashMap<String, Integer> priority = new ConcurrentHashMap<String, Integer>();
     
     static {
            priority.put( "+", 0);
            priority.put( "-", 0);
            priority.put( "*", 1);
            priority.put( "/", 1);
     }
     
     // 逆波兰表达式计算时所用的栈
     private Stack<Object> reversePolishStack = new Stack<Object>();
     // 存储操作符
     private Stack<String> operatorStack = new Stack<String>(); 
     
     // 正常的中缀表达式,如3*(1+2)
     private String formular;
     
     /**
      * 参数是正常的中缀表达式,如3*(1+2)
      * */
     public ReversePolish(String formular){
            assert(formular != null);
            this. formular = formular.replace( " ", ""); // 去除所有空格
     }

     public String getFormular() {
            return formular;
     }

     public void setFormular(String formular) {
            this. formular = formular;
     }
     /**计算,返回结果*/
     public Integer calc(){
           List<Object> rpFormular = resolveFormular();
           Integer result = 0;
           
            for(Object obj : rpFormular){
                 if(obj instanceof Integer){
                      reversePolishStack.push((Integer) obj);
                } else {
                     String op = (String) obj;
                     Integer i = (Integer)reversePolishStack.pop();
                     Integer j = (Integer)reversePolishStack.pop();
                     
                      if(op.equals( "+")){
                           result = j + i;
                     } else if(op.equals( "-")){
                           result = j - i;
                     } else if(op.equals( "*")){
                           result = j * i;
                     } else {
                           result = j / i;
                     }
                     
                      reversePolishStack.push(result);
                }
           }
           
           
            return (Integer) reversePolishStack.pop();
     }
     
     public void testResolveFormular(){
           List<Object> rpFormular = resolveFormular();
            for(Object o : rpFormular){
                System. out.print(o + " ");
           }
           
     }
     
     /**
      * 将正常的中缀表达式转换成逆波兰表达式
      * */
     private List<Object> resolveFormular(){
            // 先切分formular,找出所有数字和运算符
            char[] array = formular.toCharArray();
            // 存放切分后的中缀表达式
           List<String> splitList = new ArrayList<String>();
           
            // 临时存储转换后的解析后的后缀 formular
           List<Object> rpFormular = new ArrayList<Object>();           
           
           StringBuilder digitBuilder = new StringBuilder();
           
            for( int i = 0; i < array. length; i++){
                 if(Character. isDigit(array[i])){
                     digitBuilder.append(array[i]);
                } else {
                      if(digitBuilder.length() > 0){
                          splitList.add(digitBuilder.toString());
                           digitBuilder.delete(0, digitBuilder.length());
                     }
                     
                     splitList.add(array[i] + "");                   
                }
           }
           
            if(digitBuilder.length() > 0){
                splitList.add(digitBuilder.toString());
           }
           
            for(String s : splitList){
                Integer num = null;
                
                 try {
                     num = Integer. parseInt(s);
                } catch (Exception e) {
                }
                
                 if(num != null){      // 如果是数字,加入rpFormular列表
                     rpFormular.add(num);
                } else {    // 如果是运算符
                      if( operatorStack.isEmpty() || s.equals("(")){ // 如果运算符Stack为空或者是左括号,压入运算符栈
                            operatorStack.push(s);
                     } else {    // 如果运算符Stack不为空                        
                           String top = operatorStack.peek(); //获取栈顶元素,但不弹出栈顶元素
                           Integer topPriority = priority.get(top);   // 获取栈顶运算符优先级

                            if(topPriority != null){    // 如果栈顶不是左括号
                                 // 如果运算符是右括号
                                 if(s.equals( ")")){
                                      while( true){     // 依次弹出运算符栈的栈顶元素,直到左括号被弹出为止
                                           String element = operatorStack.pop();
                                           
                                           if(element.equals( "(")){
                                                 break;
                                           } else {
                                                rpFormular.add(element);
                                           }
                                     }
                                     
                                } else if( priority.get(s) <= topPriority){   //或者优先级低于或等于栈顶运算符优先级
                                      while( priority.get(s) <= topPriority){
                                          rpFormular.add( operatorStack.pop()); 
                                           
                                           if( operatorStack.empty()){
                                                 break;
                                           }
                                           topPriority = priority.get(operatorStack .peek());                                        
                                     }
                                      operatorStack.push(s);
                                } else {    // 如果s的优先级大于栈顶运算符的优先级,压入运算符栈
                                      operatorStack.push(s);
                                }
                           } else {    // 如果栈顶是左括号,压入运算符栈
                                 operatorStack.push(s);
                           }                          
                     }
                }
           }
           
            while(! operatorStack.empty()){
                rpFormular.add( operatorStack.pop());
           }
           
            return rpFormular;
           
     }
     
     public static void main(String[] args) {
           ReversePolish polish = new ReversePolish("9+(3-1)*3+10/2" );
           
           System. out.println(polish.calc());
     }
     
     
}

输出结果:

20

你可能感兴趣的:(逆波兰表达式)