算法学习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);
}
}