package com.coding.basic.stack.expr;
import com.coding.basic.stack.Stack;
import com.coding.basic.stack.StackUtil;
import com.coding.basic.stack.expr.util.ExprIterator;
import com.coding.basic.stack.expr.util.FixExprUtil;
import com.coding.basic.stack.expr.util.Operator;
public class InfixExpr {
String expr = null;
public InfixExpr(String expr) {
this.expr = expr;
}
public float evaluate() {
//数据栈
Stack<Float> dataStack = new Stack<>();
//操作栈
Stack<Operator> operStack = new Stack<>();
parseExpr(dataStack,operStack);
return summary(dataStack,operStack);
}
/**
* 拆分数据与运算符于两个栈中
*
* @return
*/
private void parseExpr(Stack<Float> dataStack,Stack<Operator> operStack) {
ExprIterator it = new ExprIterator(expr);
while(it.hasNext()){
String element = it.next();
if (Operator.contains(element)) {
putOpersToStack(dataStack,operStack, element);
} else {
dataStack.push(Float.parseFloat(element));
}
}
validationLastOpers(dataStack,operStack);
}
/**
* 检查最后一个操作符优先级与之前是否保持统一,
* 若不统一则进行运算,使栈中运算符保持同一个优先级
* @param stacks
*/
private void validationLastOpers(Stack<Float> dataStack,Stack<Operator> operStack) {
Object[] opers = StackUtil.getTop(operStack, 2);
Operator thisOper = (Operator) opers[0];
Operator preOper = (Operator) opers[1];
if(thisOper.getLevel()!=preOper.getLevel()){
calculateToStack(dataStack,operStack,false);
}
}
/**
* 运算符压栈
* @param stacks
* @param c
*/
private void putOpersToStack(Stack<Float> dataStack,Stack<Operator> operStack, String c) {
Operator thisOper = Operator.getOperator(c);
if (!operStack.isEmpty()) {
Operator preOper = operStack.peek();
if (preOper.getLevel() > thisOper.getLevel()) {
calculateToStack(dataStack,operStack,false);
}
}
operStack.push(thisOper);
}
/**
* 运算距栈顶最近两个元素的值并压回原栈
* @param stacks
* stacks[0]运算符,stacks[1]数据
* @param isReverse
* 当isReversed为true时会交换两个元素的位置
*/
private void calculateToStack(Stack<Float> dataStack,Stack<Operator> operStack,boolean isReverse){
float a,b;
if(isReverse){
a = dataStack.pop();
b = dataStack.pop();;
}else{
b = dataStack.pop();;
a = dataStack.pop();;
}
Operator oper = operStack.pop();
float res = FixExprUtil.calculate(a,oper,b);
dataStack.push(res);
}
/**
* 汇总结果
* @param stacks
* @return
*/
private float summary(Stack<Float> dataStack,Stack<Operator> operStack) {
StackUtil.reverse(dataStack);
StackUtil.reverse(operStack);
while (!operStack.isEmpty()) {
calculateToStack(dataStack,operStack,true);
}
return dataStack.pop();
}
}