借助栈实现表达式求值
表达式求值
http://www.nowcoder.com/questionTerminal/9566499a2e1546c0a257e885dfdbf30d
提交了7次才全部通过。。
代码还有很多可以优化的地方,如下,可能有考虑不全的情况,欢迎指正~
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.regex.Pattern; public class Main { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String str = ""; while ((str = reader.readLine()) != null){ String pattern = "[^\\d|()()*+\\-/]"; if (!Pattern.compile(pattern).matcher(str).find()){ String[] expressions = str.split(""); // 转换表达式 final List<Object> suffix = infixToSuffix(expressions); // 计算结果 System.out.println(evaluate(suffix)); } else System.out.println(-1); } reader.close(); } /** * 执行计算 * @param suffix 后缀表达式 * @return 返回Integer结果 */ public static Integer evaluate(List<Object> suffix){ if (null == suffix || suffix.size() == 0) return -1; Stack<Integer> nums = new Stack<>(); // 存储数字 for (int i = 0; i < suffix.size(); i++) { if (suffix.get(i) instanceof Integer) { // 遇到数字则入栈 nums.push(Integer.parseInt(String.valueOf(suffix.get(i)))); } else if (suffix.get(i) instanceof String && nums.size() >= 2){ // 遇到运算符,执行运算 switch (String.valueOf(suffix.get(i))){ case "+": nums.push(nums.pop() + nums.pop()); break; case "-": Integer pop1 = nums.pop(); Integer pop2 = nums.pop(); nums.push(pop2 - pop1); break; case "*": nums.push(nums.pop() * nums.pop()); break; case "/": Integer denominator = nums.pop(); Integer numerator = nums.pop(); if (denominator == 0) return -1; else nums.push(numerator / denominator); break; } } else return -1; } Integer res = 0; while (!nums.isEmpty()) { res = nums.pop(); } return res; } /** * 中缀表达式转后缀表达式(逆波兰表达式) * @param expressions 表达式字符串数组 * @return 返回后缀表达式 */ public static List<Object> infixToSuffix(String[] expressions){ if (null == expressions || expressions.length == 0) return null; Stack<String> stack = new Stack<>(); StringBuilder builder = new StringBuilder(); List<Object> result = new ArrayList<>(); for (int i = 0; i < expressions.length; i++) { if (i == 0 && !Character.isDigit(expressions[0].charAt(0)) && !expressions[0].equals("(") && !expressions[0].equals("(")){ builder.append(expressions[0]); continue; } if (Character.isDigit(expressions[i].charAt(0))){ // 遇到数字,拼接起来,还原原数 builder.append(expressions[i]); } else { if (builder.length() != 0){ // 将还原后的数字存起来 result.add(Integer.parseInt(builder.toString())); builder.delete(0, builder.length()); } switch (expressions[i]){ case "+": case "-": if (expressions[i].equals("-") && i != 0 && (expressions[i - 1].equals("(") || expressions[i - 1].equals("("))) builder.append(expressions[i]); // +和-优先级相同且最低,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈 else if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("(")) stack.push(expressions[i]); else { // 当栈不为空且栈顶元素不是左括号时,将栈元素依次输出,直到栈为空,再压入当前运算符 while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("(")) result.add(stack.pop()); stack.push(expressions[i]); } break; case "*": case "/": // *和/优先级相同且大于+和-,小于括号,当栈为空或栈顶元素为( 时直接入栈,注意,左括号只有遇到右括号才执行出栈 if (stack.isEmpty() || stack.peek().equals("(") || stack.peek().equals("(")) stack.push(expressions[i]); else { // 当栈不为空且栈顶元素不是左括号,同时栈顶元素优先级大于等于自己时,将栈元素依次输出,直到栈为空,再压入当前运算符 while (!stack.isEmpty() && !stack.peek().equals("+") && !stack.peek().equals("-") && !stack.peek().equals("(") && !stack.peek().equals("(")) result.add(stack.pop()); stack.push(expressions[i]); } break; case "(": case "(": // 遇到左括号直接入栈 stack.push(expressions[i]); break; case ")": case ")": // 遇到右括号,当栈不为空且栈顶元素不是左括号时,输出栈元素,直到栈为空或者遇到了左括号。注意这里不执行入栈操作 while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("(")) result.add(stack.pop()); // 因为遇到左括号而停止出栈时,需要将左括号出栈 if (!stack.isEmpty()) stack.pop(); break; } } } // 先清空builder if (builder.length() != 0){ result.add(Integer.parseInt(builder.toString())); builder.delete(0, builder.length()); } // 最后一步,将栈中剩余元素全部输出 while (!stack.isEmpty()) result.add(stack.pop()); return result; } }