JAVA 逆波兰表达式

package com.acwer;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NbolExpress {

    public static void main(String[] args) {
        String str="1+((2+3)*4)-5";
        List<String> 操作列表 = decode(字符转Ls(str));
        System.out.println(String.join(",", 操作列表));
        System.out.println(计算(操作列表));
    }

    public static double 计算(List<String> 逆波兰表达式){

        Map<String, Integer> 运算符优先级 = 获取运算符优先级();
        double sum=0;
        Stack<Double> stack=new Stack<Double>();

        for (String s : 逆波兰表达式) {
            if(运算符优先级.containsKey(s)){
                switch (s){
                    case "+":
                        stack.push(stack.pop()+stack.pop());
                        break;
                    case "-":
                        {
                            Double a=stack.pop();
                            Double b=stack.pop();
                            stack.push(b-a);
                        }
                        break;
                    case "*":
                        stack.push(stack.pop()*stack.pop());
                        break;
                    case "/":
                        {
                            Double a=stack.pop();
                            Double b=stack.pop();
                            stack.push(b/a);
                        }
                        break;
                }
            }else {
                stack.push(Double.valueOf(s));
            }
        }
        sum=stack.pop();
        return sum;

    }

    public static Map<String,Integer> 获取运算符优先级(){
        return new HashMap<String,Integer>(){
            {
                put("+",1);
                put("-",1);
                put("*",2);
                put("/",2);
                put("(",0);
                put(")",0);
            }
        };
    }

    public static List<String> decode(List<String> 操作列表){

        Stack<String> 操作符=new Stack<>();
        Stack<String> 运算符=new Stack<>();

        Map<String,Integer> 优先级=获取运算符优先级();
        String 符号="+-*/()";
        for (String s : 操作列表) {
            boolean 是运算符 = 符号.contains(s);
            if(!是运算符) 操作符.add(s);
            else {
                //运算符逻辑开始
                //1.如果是左括号或运算符栈为空,直接入栈
                if(s.equals("(")||运算符.isEmpty()){
                    运算符.push(s);
                }
                //2.如果是右括号
                else if(s.equals(")")){
                    while (!运算符.isEmpty()&&!运算符.peek().equals("(")){
                        操作符.add(运算符.pop());
                    }
                    运算符.pop();
                }
                //3.优先级小于等于当前栈顶元素
                else if(优先级.get(s)<=优先级.get(运算符.peek())){
                   do {
                       操作符.add(运算符.pop());
                   }while (!运算符.isEmpty()&&优先级.get(s)<=优先级.get(运算符.peek()));
                   运算符.add(s);
                }
                //4.优先级大于当前栈顶元素
                else if(优先级.get(s)>优先级.get(运算符.peek())){
                    运算符.add(s);
                }
            }

        }
        //将所有栈里面的元素加入操作符
        while (!运算符.isEmpty()){
            操作符.add(运算符.pop());
        }

        return 操作符;
    }
    //字符拆分
    public static List<String> 字符转Ls(String str){
        //拆分符号
        //String 符号="+-*/()";
        Pattern compile = Pattern.compile("(\\d(\\.*))+");
        Matcher matcher = compile.matcher(str);
        List<String> ls=new ArrayList<>();
        int preEnd=-1;
        while (matcher.find()){
            String group = matcher.group(0);
            if(preEnd==-1){
                preEnd=matcher.end();
                ls.add(group);
                continue;
            }
            int start = matcher.start();

            for (int i = preEnd; i < start; i++) {
                String 符号 = str.substring(i, i + 1);
                ls.add(符号);
            }
            ls.add(group);

            preEnd= matcher.end();
        }
        return ls;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值