算法学习2

算法学习2

用堆栈简单实现加减乘除的计算,

实现方案为把中缀表达式通过堆栈换成后缀表达式并计算

例:

中缀表达式为:a-b/c+s

转换成后缀表达式:abc/-s+

我是在中国大学慕课网上面学习的数据结构这门课程,简单实现下课程里说的堆栈的用法

package com.example.demo.algorithm;

import java.util.*;

/**
 * @author Aloli
 * @date 2020/8/25 16:23
 */
public class CalculationRules {

    /**
     * 一个数字由多个字符组成
     */
    private List<Character> NUMBER_LIST= new ArrayList<>();

    /**
     * 一个参数由多个字符组成
     */
    private List<Character> FIELD_LIST= new ArrayList<>();

    /**
     * 运算符栈
     */
    private Stack<Character> OPERATOR_STACK= new Stack<>();

    /**
     * 数值栈
     */
    private Stack<Double> NUMBER_STACK= new Stack<>();

    /**
     * 算术运算符
     */
    private final char[] ARITHMETIC_OPERATOR = {'+','-','*','/','(',')'};

    /**
     * {a}->代表有个key为a的字段 通过params.get("a")获取value,value为数字
     */
    private final char[] FIELD_IDENTIFIER = {'{','}'};


    /**
     * if is 0 , NUMBER_LIST.add
     * if is 1 , FIELD_LIST.add
     */
    private int LIST_IDENTIFIER = 0;

    /**
     * 计算表达式
     */
    private String rules = "";

    public CalculationRules(String rules){
        this.rules = rules;
    }

    public CalculationRules(){

    }

    /**
     * 中缀表达式->后缀表达式 并计算
     * @param rule
     * @param params
     * @return
     */
    public double analysisRules(String rule, Map<String,Double> params){
        if(rule==null||rule.equals("")){
            return 0D;
        }
        char[] chars = rule.toCharArray();
        for (char c : chars) {
            if(isArithmeticOperator(c)){
                if(NUMBER_LIST.size()>0){
                    NUMBER_STACK.push(getNumber());
                }
                if(OPERATOR_STACK.empty()){
                    OPERATOR_STACK.push(c);
                }else {
                    while (!OPERATOR_STACK.empty()&&getPriority(c)&&NUMBER_STACK.size()>1){
                        System.out.println(OPERATOR_STACK.toString()+" "+ c);
                        System.out.println(NUMBER_STACK.toString());
                        getResult(OPERATOR_STACK.pop());
                    }
                    if(c!=ARITHMETIC_OPERATOR[5]){
                        OPERATOR_STACK.push(c);
                    }
                }
                continue;
            }
            if(isLeftFieldOperator(c)){
                LIST_IDENTIFIER=1;
                continue;
            }
            if(isRightFieldOperator(c)){
                LIST_IDENTIFIER=0;
                NUMBER_STACK.push(getFieldNumber(params));
                continue;
            }
            if(LIST_IDENTIFIER==0){
                NUMBER_LIST.add(c);
            }else if(LIST_IDENTIFIER==1){
                FIELD_LIST.add(c);
            }
        }
        while (!OPERATOR_STACK.isEmpty()){
            getResult(OPERATOR_STACK.pop());
        }
        return NUMBER_STACK.pop();
    }

    /**
     * 中缀表达式->后缀表达式
     * @param params
     * @return
     */
    public void analysisRules(Map<String,Double> params){
        analysisRules(rules,params);
    }

    /**
     * 如果当前运算符b优先级高,则返回false(如果b为最高优先级,返回true)
     * 原则:先乘除,后加减,从左到右,有括号先算括号
     * @param b
     * @return
     */
    private boolean getPriority(char b){
        char a = OPERATOR_STACK.peek();
        /**
         * 说明此时括号里面已经算完了,值已经存入数值栈,将左括号弹出
         */
        if(a==ARITHMETIC_OPERATOR[4] && b==ARITHMETIC_OPERATOR[5]){
            OPERATOR_STACK.pop();
            return false;
        }
        /**
         * a为左括号,b为运算符,不计算
         */
        if(a==ARITHMETIC_OPERATOR[4]||b==ARITHMETIC_OPERATOR[4]){
            return false;
        }
        /**
         * b为右括号,a为运算符,执行计算
         */
        if(b==ARITHMETIC_OPERATOR[5]){
            return true;
        }
        /**
         * b为左括号,不计算
         */
        if(b==ARITHMETIC_OPERATOR[4]){
            return false;
        }
        /**
         * a,b都为运算符,b为最低优先级,执行计算
         */
        if(b==ARITHMETIC_OPERATOR[0]||b==ARITHMETIC_OPERATOR[1]){
            return true;
        }
        /**
         * a,b都为运算符,a为最高优先级,执行计算
         */
        if(a==ARITHMETIC_OPERATOR[2] || a==ARITHMETIC_OPERATOR[3]){
            return true;
        }
        return false;
    }

    /**
     * 计算加减乘除
     * @param c
     */
    private void getResult(char c){
        Double start = NUMBER_STACK.pop();
        Double end = NUMBER_STACK.pop();
        if(c==ARITHMETIC_OPERATOR[0]){
            NUMBER_STACK.push(end+start);
        }
        if(c==ARITHMETIC_OPERATOR[1]){
            NUMBER_STACK.push(end-start);
        }
        if(c==ARITHMETIC_OPERATOR[2]){
            NUMBER_STACK.push(end*start);
        }
        if(c==ARITHMETIC_OPERATOR[3]){
            NUMBER_STACK.push(end/start);
        }
    }

    /**
     * 获取参数值
     * @param params
     * @return
     */
    private double getFieldNumber(Map<String,Double> params){
        StringBuilder sb = new StringBuilder("");
        FIELD_LIST.forEach(character -> {
            sb.append(character);
        });
        FIELD_LIST.clear();
        return params.get(sb.toString());
    }

    /**
     * 获取数值
     * @return
     */
    private double getNumber(){
        StringBuilder sb = new StringBuilder("");
        NUMBER_LIST.forEach(character -> {
            sb.append(character);
        });
        NUMBER_LIST.clear();
        return Double.parseDouble(sb.toString());
    }

    /**
     * 代表一个key的结束
     * @param c
     * @return
     */
    private boolean isRightFieldOperator(char c){
        return c == FIELD_IDENTIFIER[1];
    }

    /**
     * 代表一个key的开始
     * @param c
     * @return
     */
    private boolean isLeftFieldOperator(char c){
        return c == FIELD_IDENTIFIER[0];
    }

    /**
     * 运算符
     * @param c
     * @return
     */
    private boolean isArithmeticOperator(char c){
        for (char cc: ARITHMETIC_OPERATOR){
            if(cc==c){
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        String abc = "1.25-{a}*{b}-((1+{c}/4))";
        Map<String,Double> map = new HashMap<>();
        map.put("a",1D);
        map.put("b",1D);
        map.put("c",1D);
        CalculationRules calculationRules = new CalculationRules();
//        double v = calculationRules.analysisRules(abc, map);
//        System.out.println(v);
        /**
         * 重新用一个复杂表达式来计算了一下。修改了点bug
         */
        String rule = "1-{mpublicationprice}*{mdiscount}*(1+{customerpolicyreturn})*{mediapolicydiscounts}*(1-{mediapolicycashback})/(1+{servicerate})/{cpublicationprice}/{cdiscount}/{customerpolicydiscounts}/(1-{customerpolicycashback})/(1+{mediapolicyreturn}+{mediaagentpolicyreturn})*(1-{mediaagencypolicycashback})";


        String aaa = "1-1.0*1.0*(1+0.0)*1.0*(1-0.0)/(1+0.04)/1.0/1.0/1.0/(1-0.0)/(1+0.0+0.0)*(1-0.0909)";
        Map<String,Double> params = new HashMap<>();
        params.put("customerpolicycashback",0.0000);
        params.put("mediaagencypolicycashback",0.0909);
        params.put("mdiscount",1.0);
        params.put("mediapolicycashback",0.0);
        params.put("mpublicationprice",1.0);
        params.put("servicerate",0.04);
        params.put("customerpolicydiscounts",1.00000000000000000000);
        params.put("mediapolicyreturn",0.0);
        params.put("mediapolicydiscounts",1.0);
        params.put("mediaagentpolicyreturn",0.0);
        params.put("cdiscount",1.0);
        params.put("customerpolicyreturn",0.0000);
        params.put("cpublicationprice",1.0);
        double result = calculationRules.analysisRules(rule, params);
        System.out.println(result);
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值