zoukankan      html  css  js  c++  java
  • 逆波兰表达式完整实现

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

    因此直接上代码实现过程

    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;
        }
    }

    运行结果:

  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/ftx3q/p/15725166.html
Copyright © 2011-2022 走看看