package datastructure; import java.util.stream.Stream; public class DoubleLinkedListDemo { public static void main(String[] args) { //根据前面老师思路,完成表达式的运算 String expression = "4/2+1"; //创建两个栈,数栈,一个符号栈 ArrayStack numStack = new ArrayStack(10); ArrayStack operStack = new ArrayStack(10); //定义需要的相关变量 int index = 0;//用于扫描 int num1 = 0; int num2 = 0; int operation = 0; int res = 0; char ch = ' '; //将每次扫描得到 char 保存到 ch String keepNum = ""; //用于拼接 多位数 //开始 while 循环的扫描 expression while (true){ //依次得到 expression 的每一个字符 ch = expression.substring(index,index + 1).charAt(0); //判断 ch 是什么,然后做相应的处理 if (operStack.isOperation(ch)){//如果是运算符 //判断当前的符号栈是否为空 if(!operStack.isEmpty()){ if (operStack.priority(ch) <= operStack.priority(operStack.peek())){ num1 = numStack.pop(); num2 = numStack.pop(); operation = operStack.pop(); res = numStack.cal(num1,num2,operation); //然后将当前的操作符入符号栈 operStack.push(ch); //把运算的结果如数栈 numStack.push(res); }else { //如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈. operStack.push(ch); } }else { //如果为空直接入符号栈. operStack.push(ch); } }else {//如果是数,则直接入数栈 //numStack.push(ch - 48); //? "1+3" '1' => 1 //分析思路 //1. 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数 //2. 在处理数,需要向 expression 的表达式的 index 后再看一位, // 如果是数就进行扫描,如果是符号才入栈 //3. 因此我们需要定义一个变量 字符串,用于拼接 keepNum += ch; if (index == expression.length() - 1){ numStack.push(Integer.parseInt(keepNum)); }else { if (operStack.isOperation(expression.substring(index + 1,index + 2).charAt(0))){ numStack.push(Integer.parseInt(keepNum)); keepNum = ""; } } } index++; if (index >= expression.length()){ break; } } //当表达式扫描完毕,就顺序的从 数栈和符号栈中 pop 出相应的数和符号,并运行. while (true){ //如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】 if (operStack.isEmpty()){ break; } num1 = numStack.pop(); num2 = numStack.pop(); operation = operStack.pop(); res = numStack.cal(num1,num2,operation); numStack.push(res); } //将数栈的最后数,pop 出,就是结果 System.out.printf("表达式 %s = %d",expression,numStack.pop()); } } //定义一个 ArrayStack 表示栈 class ArrayStack{ private int maxSize;// 栈的大小 private int[] stack; // 数组,数组模拟栈,数据就放在该数组 private int top = -1;// top 表示栈顶,初始化为-1 //构造器 public ArrayStack(int maxSize){ this.maxSize = maxSize; stack = new int[this.maxSize]; } //栈满 public boolean isFull(){ return top == maxSize - 1; } //栈空 public boolean isEmpty(){ return top == -1; } //入栈-push public void push(int value){ //先判断栈是否满 if (isFull()){ System.out.println("栈满"); return; } top++; stack[top] = value; } //出栈-pop, 将栈顶的数据返回 public int pop(){ //先判断栈是否空 if (isEmpty()){ //抛出异常 throw new RuntimeException("栈空"); } int value = stack[top]; top--; return value; } //显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据 public void list(){ if (isEmpty()){ System.out.println("栈空"); return; } for (int i = top; i >= 0; i--) { System.out.printf("stack[%d]=%d\n",i,stack[i]); } } //返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示 //数字越大,则优先级就越高. public int priority(int operation){ if (operation == '*' || operation == '/') return 1; else if (operation == '+' || operation == '-'){ return 0; }else { return -1; } } //判断是不是一个运算符 public boolean isOperation(char val){ return val == '+' || val == '-' || val == '*' || val =='/'; } // 计算方法 public int cal(int num1,int num2,int operation){ int res = 0; switch (operation){ case '+': res = num1 + num2; break; case '-': res = num2 - num1; break; case '*': res = num1 * num2; break; case '/': res = num2 / num1; break; default: break; } return res; } //增加一个方法,可以返回当前栈顶的值, 但是不是真正的 pop public int peek(){ return stack[top]; } }