224.基本计算器

224.基本计算器

实现一个基本的计算器来计算一个简单的字符串表达式的值。

字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。

import java.util.Stack;

public class _224_基本计算器1 {
    public int calculate(String s) {
        Stack<Integer> stack1 = new Stack<>();//stack1中最多存储3个值
        Stack<Character> stack2 = new Stack<>();// stack2中最多存储2个运算符
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') { // (
                stack2.push(c);
            } else if (c == ')') { // )
                while (stack2.peek() != '(') {
                    char label = stack2.peek();
                    reversePolish(label,stack1);
                    stack2.pop();
                }
                stack2.pop();

            } else if (Character.isDigit(c)) { // 数字
                add(stack1,c,s,i);
            } else {
                if (c != ' ') {// + - * /
                    if (stack2.isEmpty()) {
                        stack2.push(c);
                    }
                    else if (stack2.peek() == '(') {
                        stack2.push(c);
                    } else if ((stack2.peek() == '+' || stack2.peek() == '-') && (c == '*' || c=='/') ) {
                        stack2.push(c);
                    } else {
                        char lable = stack2.peek();
                        reversePolish(lable,stack1);
                        stack2.pop();
                        stack2.push(c);
                    }
                }
            }
        }
        while (!stack2.isEmpty()) {
            char label = stack2.peek();
            reversePolish(label,stack1);
            stack2.pop();
        }

        return stack1.pop();
    }
    // 计算逆波兰表达式 如:1 1 -
    private void reversePolish(char label, Stack<Integer> stack1) {
        int right = stack1.pop();
        int left = stack1.pop();
        switch (label) {
            case '+' :
                stack1.push(left + right);
                break;
            case '-' :
                stack1.push(left - right);
                break;
            case '*' :
                stack1.push(left * right);
                break;
            case '/':
                stack1.push(left / right);
                break;

        }
    }

    private void add(Stack<Integer> stack1, char c, String s, int i) {
        if (stack1.isEmpty()) {
            stack1.push(c-'0');
        } else {
            if (Character.isDigit(s.charAt(i-1))){//23
                stack1.push(((int)stack1.pop())*10 + (c - '0'));
            } else {
                stack1.push(c-'0');
            }
        }
    }



}

一共用到三个函数

  • calculate 主函数
  • reversePolish 逆波兰函数(输入3个元素)例:111 2 + -> 113
  • add 数字字符串处理,例:"123" -> 123

calculate 主函数思路 示例:(1+2+(4+5+2)-3)+(6+8)

将中缀表达式转化为后缀表达式

  • 准备两个栈,stack1、stack2。stack1存储操作数,stack2存储操作符
  • 遍历字符串s每一个字符c
  • c可能的值是' ', '(', ')' , '+' , '-' , '*' , '/','数字字符'
  • 操作符优先级:加减 < 乘除 ,先入栈的加减 > 后入栈的加减, 先入栈的乘除>后入栈的乘除
char c 操作
'(' 压入stack2
')' 依次将stack2中元素出栈到stack2,直至遇到'(' ,将'('出栈
'+' 将栈中比'+'优先级高的操作符出栈到stack1,没有的话就不出栈。将'+'入栈 如果栈顶是'+'或'-'则'+'或'-'优先级比'+'高
'-' 类似于'+'
'*' 类似于'+'
'/' 类似于'+'
'数字' 如果stack1为空,直接将c-'0'压入stack1。如果c的前一个字符是数字,将栈stack1栈顶元素弹出乘以10加c-'0'的值 如111
为了区分不同位置加号,使用'+_数字'表示加号
(111+2+3)/2+1 -> 111 2 + 3 + 2 / 1 +
c stack1 stack2 stack1优化
'(' [] [] []
'1' [] ['('] []
'1' [1] ['('] [1]
'1' [11] ['('] [11]
'+_1' [111] ['('] [111]
'2' [111] ['(', '+_1'] [111]
'+_2' [111, 2] ['(', '+_2'] [111, 2]
'3' [111, 2,'+_1'] ['(', '+_2'] [113]
')' [111, 2,'+_1',3] ['(', '+_2'] [113,3]
'/' [111, 2,'+_1',3,'+_2'] [] [116]
'2' [111, 2,'+_1',3,'+_2'] ['/'] [116]
'+_3' [111, 2,'+_1',3,'+_2',2] ['/'] [116,2]
'1' [111, 2,'+_1',3,'+_2',2,'/'] ['+_3'] [58]
[111, 2,'+_1',3,'+_2',2,'/',1] ['+_3'] [58,1]
  • 栈stack1可以优化,当stack1入栈操作符时,改为直接执行逆波兰表达式(将stack1栈顶两个操作数弹出,记为left、right执行对应的加减乘除),stack1中只存操作数
  • 最后stack2中的栈顶弹出,stack1中两元素弹出,执行最后的逆波兰表达式,得到最终计算结果
原文地址:https://www.cnblogs.com/sweetorangezzz/p/12981756.html