中缀表达式求值

318 阅读1分钟

【题目】 给定一个字符串str,str是一个算数表达式,包含四则运算和括号()、[]、{}。要求返回计算结果。

【举例】 str="(3+1)*4/2",返回8。

【思路】 首选把中括号和大括号替换为小括号,接下来:

  1. 用递归处理括号内的表达式;
  2. 遍历字符数组,每取到一个完整的数就检查栈顶字符串;(1) 如果栈顶是*或者/即可优先弹栈计算;(2)如果是+或者-,入栈。
  3. 遍历完字符数组之后,栈中只剩下+和-的表达式。计算时可以从栈顶开始出栈,数字的符号后出栈;也可以将Deque看作双端队列,从队首出队,数字的符号会先出队。

总结一下:递归解决处理括号;入栈时先计算乘除,遍历完后计算加减,从而解决了符号的优先级问题。

【代码】

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String line = sc.nextLine();
            line = line.replace("[", "(");
            line = line.replace("]", ")");
            line = line.replace("{", "(");
            line = line.replace("}", ")");
            int n = value(line.toCharArray(), 0)[0];
            System.out.println(n);
        }
    }

    private static int[] value(char[] chars, int i) {
        Deque<String> deque = new LinkedList<>();
        int pre = 0;
        int[] bra = null;
        while (i < chars.length && chars[i] != ')') {
        	// 取完整的数字
            if (chars[i] >= '0' && chars[i] <= '9') {
                pre  = pre * 10 + chars[i] - '0';
            } else if (chars[i] != '(') { // 遇到+-*/),表示数字结束,将数字放入deque,再将符号放入deque,重置pre
                addNum(deque, pre);
                deque.offerLast(String.valueOf(chars[i]));
                pre = 0;
            } else { // 遇到'(',进入递归
                bra = value(chars, i + 1);
                pre = bra[0];
                i = bra[1];
            }
            i++;
        }
        addNum(deque, pre);
        return new int[]{getNum(deque), i};
    }
	
    // 数字放入栈中。先看栈顶元素,若是*或/则进行计算,消除*/;若是+-则直接放入栈中
    private static void addNum(Deque<String> deque, int v) {
        if (deque.isEmpty()) {
            deque.addLast(String.valueOf(v));
            return;
        }
        String s = deque.peekLast();
        if (s.equals("*") || s.equals("/")) {
            deque.pollLast();
            Integer v2 = Integer.parseInt(deque.pollLast());
            v = s.equals("*") ? v * v2 : v2 / v;
        }
        deque.addLast(String.valueOf(v));
    }

	// 从只有+-的栈中计算结果
    private static int getNum(Deque<String> deque) {
        boolean add = true;
        int res = 0;
        while (!deque.isEmpty()) {
            String s = deque.pollFirst();
            if (s.equals("+")) {
                add = true;
            } else if (s.equals("-")) {
                add = false;
            } else {
                int v = Integer.parseInt(s);
                res = add ? (res + v) : (res - v);
            }
        }
        return res;
    }
}