import java.util.HashMap;
import java.util.Map;
public class SimpleArithmeticTest {
public static void main(String[] args) {
// 设置优先级
Map<String, Integer> priorityMap = new HashMap<>();
priorityMap.put("+", 1);
priorityMap.put("-", 1);
priorityMap.put("*", 2);
priorityMap.put("/", 2);
// 数字与符号之间需使用空格隔开
String str01 = "1 + 3 * 4 - 2 + 12 / 3"; // 15
String str02 = "1 * 5 - 3 + 6 / 2 + 1 + 1"; // 7
String str03 = "1 + 3 - 2 + 15 / 3 - 4 * 1"; // 3
System.out.println(calculate(priorityMap, str01));
System.out.println(calculate(priorityMap, str02));
System.out.println(calculate(priorityMap, str03));
}
private static Integer calculate(Map<String, Integer> priorityMap, String str) {
String[] s = str.split(" ");
// 声明两个栈,一个用来存数字,一个用来存符号
MyArrayStack<Integer> numberStack = new MyArrayStack<>(str.length());
MyArrayStack<String> symbolStack = new MyArrayStack<>(str.length());
for (int i = 0; i < s.length; i++) {
if (i % 2 == 0) { // 是数字位
if (i == s.length - 1) { // 最后一位数字
// 数字栈里只可能存一个数字或者两个数字
// 符号栈里只可能存一个符号或者两个符号,如果存在两个符号,栈顶的符号优先级肯定比栈底的高,要优先计算
int nowNumber = Integer.parseInt(s[i]);
int result = 0;
while(numberStack.get() != null){ // 其实最多只会遍历两次
// 将栈顶数字与当前数字进行计算
result = getReult(nowNumber, numberStack.pop(), symbolStack.pop()); // 当前值为算术式的右侧数字,从数字栈出栈的数字为算数式左侧数字
nowNumber = result; // 第二次就要拿第一次计算的结果作为下一次计算的当前值
}
return result;
}
// 不是处理最后一位数字的时候执行的入栈操作
numberStack.push(Integer.parseInt(s[i]));
} else { // 是符号位
String nowSymbol = s[i]; // 当前符号
if (!symbolStack.isEmpty()) {
// 将当前的符号与已存入的符号的优先级进行比对
String lastSymbol = symbolStack.get(); // 栈顶符号,使用get,不是用pop,是为了防止不满足如下的情况,栈顶也出栈
// 如果当前的符号优先级小于或者等于栈顶符号,则需要取出数字栈中的栈顶两位进行运算
while (priorityMap.get(nowSymbol) <= priorityMap.get(lastSymbol)) {
symbolStack.pop(); // 满足当前条件的话,栈顶元素需出栈
int result = getReult(numberStack.pop(), numberStack.pop(), lastSymbol); // 先出栈的数字为算术式的右侧数字,第二次出栈的数字为算数式左侧数字
// 将运算的result再次入到数字栈,将当前符号入到符号栈中
numberStack.push(result);
if (null != symbolStack.get()) { // 栈顶符号,使用get,不是用pop,是为了防止不满足优先级的时候,栈顶也出栈
lastSymbol = symbolStack.get();
} else {
break;
}
}
}
// 1.字符栈还为空
// 2.如果当前的符号优先级大于栈顶符号,则将符号入符号栈栈顶,下一步就是将数字入数字栈顶
symbolStack.push(s[i]);
}
}
return numberStack.pop();
}
/**
* 根据符号进行运算
* @param frontNumber
* @param behindNumber
* @param symbol
* @return
*/
private static int getReult(int behindNumber, int frontNumber, String symbol) {
if ("+".equals(symbol)){
return frontNumber + behindNumber;
} else if("-".equals(symbol)){
return frontNumber - behindNumber;
} else if("*".equals(symbol)){
return frontNumber * behindNumber;
} else if("/".equals(symbol)){
return frontNumber / behindNumber;
} else {
return 999999999;
}
}
}
/**
* 使用数组实现的一个栈
*
* @param <T>
*/
class MyArrayStack<T> {
private T[] arrayStack;
private int stackSize = 0; // 当前栈中已存的数据量
/**
* 构造函数,参数值为初始化数组的长度
*
* @param length
*/
public MyArrayStack(int length) {
arrayStack = (T[]) new Object[length];
}
/**
* 入栈一个元素
* 如果stackSize大于length的0.75,则扩大二倍,
*
* @param t
*/
public void push(T t) {
if (stackSize > arrayStack.length * 0.75 - 1) {
T[] newArrayStack = (T[]) new Object[arrayStack.length * 2];
System.arraycopy(arrayStack, 0, newArrayStack, 0, arrayStack.length - 1);
arrayStack = newArrayStack;
}
arrayStack[stackSize++] = t;
}
/**
* 出栈一个元素
*/
public T pop() {
if (0 == stackSize) {
return null;
}
T t = arrayStack[--stackSize];
arrayStack[stackSize] = null;
return t;
}
/**
* 只用于查询栈顶元素值,不出栈
*/
public T get() {
if (0 == stackSize) {
return null;
}
T t = arrayStack[stackSize - 1]; // 不使用--stackSize,是为了保证不改变stackSize大小
return t;
}
/**
* 当前栈是否为空
*
* @return
*/
public boolean isEmpty() {
return 0 == stackSize;
}
}
结果:
15
7
3