使用栈结构计算中缀表达式
栈中元素的顺序是先进后出,添加的元素总在栈顶,出栈也是先出栈顶,就像弹夹一样。中缀表达式是我们人计算表达式的方式例如 (2*3-2)*(3+3*3)我们总会括号优先,* / 优先于+ –
使用栈结构计算这个表达式的核心思想就是搞两个栈,一个存放数字,一个存放符号。
package com.dfsn.cloud.eureka; public class Stack<T> { private Object arr[]; private int top = -1; public Stack(int capacity) { arr = new Object[capacity]; } public void push(T t) { if (isFull()) { throw new RuntimeException("栈已满,无法添加"); } top++; arr[top] = t; } public T pop() { if (isEmpty()) { throw new RuntimeException("栈为空,没有元素"); } return (T) arr[top--]; } public T peek() { if (isEmpty()) { throw new RuntimeException("栈为空,没有元素"); } return (T) arr[top]; } public boolean isEmpty() { return top == -1; } public boolean isFull() { return top == arr.length - 1; } public void show() { for (int i = 0; i <= top; i++) { System.out.println(arr[i]); } } public int size() { return top + 1; } }
View Code
package com.dfsn.cloud.eureka; //中缀表达式 public class NifixExpression { public int calculate(String expression) { // 限定最多10个数字 Stack<Integer> numberStack = new Stack<>(10); // 10个数字需要9个字符 Stack<String> symbolStack = new Stack<>(9); for (int i = 0; i < expression.length(); i++) { String current = expression.substring(i, i + 1); // 是数字还是字符 int symbolOrNumber = symbolOrNumber(current); // 是数字 if (symbolOrNumber == 0) { // 如果是数字,则需要判断后边的是不是数字,防止多位数 int concatNumber = concatNumber(expression.substring(i)); // 如果是多位数循环需要跳过比如 123+2 // 取出123 后下一个要取 + 也就是 i+(123.length),但循环本身会自增1所以只能+123.length-1 i += (concatNumber + "").length() - 1; // 入数字栈 numberStack.push(concatNumber); } else {// 是符号 if (symbolStack.isEmpty()) { // 符号栈没有符号,则入栈 symbolStack.push(current); } else { // 如果是左括号直接入栈 if (current.equals("(")) { symbolStack.push(current); continue; } // 如果是右括号,则需要每次弹出一个符号和两个数字做运算 // 直到碰到 ( 符号结束,并把 ( 出栈 if (current.equals(")")) { while (true) { if (symbolStack.peek().equals("(")) { symbolStack.pop(); break; } else { int number2 = numberStack.pop(); int number1 = numberStack.pop(); String symbol = symbolStack.pop(); int result = operation(number1, number2, symbol); numberStack.push(result); } } continue; } // 拿出符号栈顶元素和当前符号对比,如果栈顶符号是 ( 则为0,因为它只有遇到)才有意义 String stackTop = symbolStack.peek(); int stackTopPriority = priority(stackTop); int priority = priority(current); // 如果当前符号优先级大于栈顶符号优先级,将当前符号添加到栈顶 if (priority > stackTopPriority) { symbolStack.push(current); } else { // 如果当前符号优先级小于等于栈顶运算符优先级,则从符号栈顶弹出一个符号 // 从数字栈中弹出两个数字做运算 注意:栈顶元素在右 // 将结果入数字栈,最后将当前运算符入符号栈 int number2 = numberStack.pop(); int number1 = numberStack.pop(); String symbol = symbolStack.pop(); int result = operation(number1, number2, symbol); numberStack.push(result); symbolStack.push(current); } } } } // 最后两个队列可能还有元素,则顺序弹出1个符号和两个数字做运算,并且将结果入数字栈 while (true) { if (symbolStack.isEmpty()) { break; } else { int number2 = numberStack.pop(); int number1 = numberStack.pop(); String symbol = symbolStack.pop(); int result = operation(number1, number2, symbol); numberStack.push(result); } } if (numberStack.size() != 1) { throw new RuntimeException("运算异常"); } else { return numberStack.pop(); } } // 返回1表示是运算符,返回0表示是数字 public int symbolOrNumber(String expression) { if (expression.equals("+") || expression.equals("-") || expression.equals("*") || expression.equals("/") || expression.equals("(") || expression.equals(")")) { return 1; } else if (expression.equals("0") || expression.equals("1") || expression.equals("2") || expression.equals("3") || expression.equals("4") || expression.equals("5") || expression.equals("6") || expression.equals("7") || expression.equals("8") || expression.equals("9")) { return 0; } else { throw new RuntimeException("不是数字也不是运算符"); } } // 返回运算符的等级 * / 高 public int priority(String symbol) { if (symbol.equals("+") || symbol.equals("-")) { return 1; } else if (symbol.equals("*") || symbol.equals("/")) { return 2; } else if (symbol.equals("(")) { return 0; } else { throw new RuntimeException("无法识别运算符"); } } // 获取字符串中第一个连续数字 public int concatNumber(String str) { StringBuilder strNumber = new StringBuilder(); int index = 0; while (true) { if (index > str.length() - 1) { break; } String ch = str.charAt(index) + ""; if (symbolOrNumber(ch) == 0) { strNumber.append(ch); index++; } else { break; } } return Integer.parseInt(strNumber.toString()); } // 做运算 public int operation(int number1, int number2, String symbol) { switch (symbol) { case "+": return number1 + number2; case "-": return number1 - number2; case "*": return number1 * number2; case "/": return number1 / number2; default: throw new RuntimeException("运算符不正确"); } } }
View Code
版权声明:本文为zumengjie原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。