使用栈结构计算中缀表达式

栈中元素的顺序是先进后出,添加的元素总在栈顶,出栈也是先出栈顶,就像弹夹一样。中缀表达式是我们人计算表达式的方式例如 (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
原文地址:https://www.cnblogs.com/zumengjie/p/13783007.html