逆波兰表达式完整实现

  上篇中,我们只支持对整数实现,本篇完整实现,支持加减乘除和多位数、小数,思路与上篇相同。

因此直接上代码实现过程

package com.atxihua;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;

public class reversePolishMultiCalc {
    public static void main(String[] args) {
        String math="12.8+(2 - 3.55)*4+10/5.0";//去除空格,故意在-前后添加空格进行测试
        try {
            doCalc(doMatch(math));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
    * 匹配+ - * / ()运算符
    * */
    static final String SYMBOL="\\+|-|\\*|/|\\(|\\)";

    static final String LEFT="(";
    static final String RIGHT=")";
    static final String ADD="+";
    static final String MINUS="-";
    static final String TIMES="*";
    static final String DIVISON="/";

    static final int LEVEL_01=1;//+ -
    static final int LEVEL_02=2;//* /
    static final int LEVEL_HIGH=Integer.MAX_VALUE;//括号

    static Stack<String> stack=new Stack<>();
    static List<String> data= Collections.synchronizedList(new ArrayList<String>());

    /*
    * 去除所有空白
    * */

public static String replaceAllBlack(String s){
  //\\s+匹配任何空白字符,包括空格、制表符、换页符等待,等价于[\f\n\r\t\v]
  return s.replaceAll("\\s+","") ;
}
//判断是不是数字
public static boolean isNumber(String s){
        Pattern pattern=Pattern.compile("^[-\\+]?[.\\d]*$");
        return  pattern.matcher(s).matches();
    }
//判断是不是运算符
public static boolean isSymbol(String s){
    return s.matches(SYMBOL);
    }
//匹配运算等级
public static int calcLevel(String s){
        if("+".equals(s)||"-".equals(s)){
            return LEVEL_01;
        }else if("*".equals(s)||"/".equals(s)){
            return LEVEL_02;
        }else {
            return LEVEL_HIGH;
        }
    }
public static List<String> doMatch(String s){
        if(s==null||"".equals(s.trim()))throw new RuntimeException("data is empty");
        //进行简单校验,保证第一个是数字
        if(!isNumber(s.charAt(0)+""))throw new RuntimeException("data is illeagle,start not with a number");
        s=replaceAllBlack(s);
        String each;
        int start=0;
        for(int i=0;i<s.length();i++){
            if(isSymbol(s.charAt(i)+"")){
                each=s.charAt(i)+"";
               //栈为空,(操作符,或者操作符优先级大于栈顶优先级&&操作符优先级不是()优先级及是 ) 不能直接入栈
                if(stack.isEmpty()||LEFT.equals(each)
                ||((calcLevel(each)>calcLevel(stack.peek()))&&calcLevel(each)<LEVEL_HIGH)){
                    stack.push(each);
                }else if(!stack.isEmpty()&&calcLevel(each)<=calcLevel(stack.peek())){
                    //栈非空,操作符优先级小于等于栈顶优先级时出栈入列,直到栈为空,或者遇到(,最后操作符入栈
                    while (!stack.isEmpty()&& calcLevel(each)<=calcLevel(stack.peek())){
                        if(calcLevel(stack.peek())==LEVEL_HIGH){
                            break;
                        }
                        data.add(stack.pop());
                    }
                    stack.push(each);
                }else if(RIGHT.equals(each)){
                    //)操作符,依次出栈入列直到空栈或者遇到第一个)操作符,此时)出栈
                    while (!stack.isEmpty()&&LEVEL_HIGH>=calcLevel(stack.peek())){
                        if(LEVEL_HIGH==calcLevel(stack.peek())){
                            stack.pop();
                            break;
                        }
                        data.add(stack.pop());
                    }
                }
                start=i;
            }else if(i==s.length()-1||isSymbol(s.charAt(i+1)+"")){
                each=start==0?s.substring(start,i+1):s.substring(start+1,i+1);
                if(isNumber(each)){
                    data.add(each);
                    continue;
                }
                throw new RuntimeException("data not match number");
            }
        }
        //如果栈里还有元素,此时元素需要依次出栈入列,可以想象栈里剩下栈顶为/,栈底为+,应该依次出栈入列
        //可以直接反转整个stack添加到队列中
        Collections.reverse(stack);
        data.addAll(new ArrayList<>(stack));
        System.out.println(data);
        return data;
     }
//计算结果
public static Double doCalc(List<String> list){
    Double d=0d;
    if(list==null||list.isEmpty()){
        return null;
    }
    if(list.size()==1){
        System.out.println(list);
        d=Double.valueOf(list.get(0));
        return d;
    }
    ArrayList<String> list1=new ArrayList<>();
    for(int i=0;i<list.size();i++){
        list1.add(list.get(i));
        if(isSymbol(list.get(i))){
            Double d1=doTheMath(list.get(i-2),list.get(i-1),list.get(i));
            list1.remove(i);
            list1.remove(i-1);
            list1.set(i-2,d1+"");
            list1.addAll(list.subList(i+1,list.size()));
            break;
        }
    }
    doCalc(list1);
    return d;
}
//运算
    public static Double doTheMath(String s1, String s2, String symbol) {
    Double result;
    switch (symbol){
        case ADD:result=Double.valueOf(s1)+Double.valueOf(s2);break;
        case MINUS:result=Double.valueOf(s1)-Double.valueOf(s2);break;
        case TIMES:result=Double.valueOf(s1)*Double.valueOf(s2);break;
        case DIVISON:result=Double.valueOf(s1)/Double.valueOf(s2);break;
        default:result=null;
    }
    return result;
    }
}

运行结果:

 

posted @ 2021-12-23 20:41  活在记忆里的人  阅读(31)  评论(0编辑  收藏  举报