【数据结构与算法(Java)】逆波兰计算器(后缀表达式实现)

public class PolandNotation {

    /**
     * @author hoy
     * 中缀表达式 -> 后缀表达式list<String>
     * 思路:
     *      1. 创建一个堆栈,operatorStack<string> 用于保留运算符; 创建一个list,postfixList<string> 用于保留中间结果。
     *      2. 原始中缀表达式 -> 中缀表达式list<string>
     *      3. 中缀表达式list<string> -> 后缀表达式list<string>:遍历list,临时变量为 item
     *          3.1 item为数字:入栈 postfixList。
     *          3.2 item为 ( :item 入栈 operatorStack。
     *          3.3 item为 ):逐个从 operatorStack 出栈,并入栈 postfixList,直到碰到 (,且删除 (。
     *          3.4 item为*,/,+或-的运算符,循环查看operatorStack的top:
     *              3.4.1 若
     *                      a. operatorStack 为空 或
     *                      b. top为( 或
     *                      c. item 优先级大于 top
     *                    则:item 入栈 operatorStack
     *              3.4.2 否则:top 入栈 postfixList,继续 2.2.1 比较下一top
     *      4. 将字符栈中剩余字符逐个出栈,并加入输出 postfixList,返回输出list
     *
     * @param originalExpression - 原表达式,元素用空格隔开。如"7 * 4 - 20 / ( 3 + 1 )"
     * @return - 所生成的后缀表达式
     */
    public static ArrayList<String> getPostfixExpression(String originalExpression) {
        // 0. 校验参数:是否为null或者空
        if (originalExpression == null || originalExpression.isEmpty()) {
            throw new RuntimeException("expression wrong");
        }
        originalExpression = originalExpression.trim();

        // 1. 创建一个堆栈,operatorStack<string> 用于保留运算符; 创建一个list,postfixList<string> 用于保留中间结果。
        Stack<String> operatorStack = new Stack<>();
        ArrayList<String> postfixList = new ArrayList<>();
        // 2. 原始中缀表达式 -> 中缀表达式list<string>
        ArrayList<String> originalExpressionList = getExpressionList(originalExpression);
        // 3. 中缀表达式list<string> -> 后缀表达式list<string>:遍历list,临时变量为 item
        for (String item : originalExpressionList){
            // 3.1 item为数字:入栈 postfixList。
            if (item.matches("\\d+")){
                postfixList.add(item);
            }
            // 3.2 item为 ( :item 入栈 operatorStack。
            else if (item.equals("(")) {
                operatorStack.push(item);
            }
            // 3.3 item为 ):逐个从 operatorStack 出栈,并入栈 postfixList,直到碰到 (,且删除 (。
            else if (item.equals(")")) {
                while (!operatorStack.peek().equals("(")) {
                    postfixList.add(operatorStack.pop());
                }
                operatorStack.pop(); // "("出栈
            }
            // 3.4 item为*,/,+或-的运算符,循环查看operatorStack的top:
            else if (item.equals("+")
                    || item.equals("-")
                    || item.equals("*")
                    || item.equals("/")){
                // (1) 循环从 operatorStack 中出栈 top,并将top加入postfixList。
                // 当 a. operatorStack 为空 或
                //    b. top为( 或
                //    c. item 优先级大于 top
                // 时停止
                while (!operatorStack.isEmpty()
                        && !operatorStack.peek().equals("(")
                        && getPriority(item) <= getPriority(operatorStack.peek())) {
                    postfixList.add(operatorStack.pop());
                }
                // (2) item 入栈 operatorStack
                operatorStack.push(item);

            }
        }

        // 4. 将字符栈中剩余字符逐个出栈,并加入输出 postfixList,返回输出list
        while (!operatorStack.isEmpty()) {
            postfixList.add(operatorStack.pop());
        }
        return postfixList;
    }
    // for getPostfixExpression()
    public static ArrayList<String> getExpressionList(String expression) {
        ArrayList<String> expressionList = new ArrayList<>();
        StringBuilder wholeNumber = new StringBuilder();
        for (int i = 0; i < expression.length(); i++) {
            String item = expression.substring(i, i + 1);
            if (item.equals(" ")) {
                continue;
            } else if (isNumber(item)) {
                wholeNumber.append(item);
                if (i == expression.length() - 1 || !isNumber(expression.substring(i + 1, i + 2))) {
                    expressionList.add(wholeNumber.toString());
                    wholeNumber = new StringBuilder();
                }
            } else if (isOperatorOrBracket(item)) {
                expressionList.add(item);
            }
        }
        return expressionList;
    }
    // for getExpressionList()
    private static boolean isNumber(String item) {
        switch (item) {
            case "0":
            case "1":
            case "2":
            case "3":
            case "4":
            case "5":
            case "6":
            case "7":
            case "8":
            case "9":
                return true;
            default:
                return false;
        }
    }
    // for getExpressionList()
    private static boolean isOperatorOrBracket(String item) {
        return item.equals("+")
                || item.equals("-")
                || item.equals("*")
                || item.equals("/")
                || item.equals("(")
                || item.equals(")");
    }
    // for all two method
    private static int getPriority(String operator) {
        switch (operator) {
            case "*":
            case "/":
                return 1;
            case "+":
            case "-":
                return 0;
            default:
                return -1;
        }
    }

    /**
     * @author hoy
     * 通过所给的后缀表达式,计算结果。
     * @param postfixExpressionList - 后缀表达式的list。如"7,4,*,20,3,1,+,/,-"
     * @return
     */
    public static int calculateByPostfixExpression(ArrayList<String> postfixExpressionList) {
        // 1. 设置数字栈栈,存放各个元素
        Stack<Integer> digitStack = new Stack<>();

        // 2. 遍历栈
        for (String item : postfixExpressionList) {
            // 2.1 若item为数字(用正则表达式判断):入栈
            if (item.matches("\\d+")){
                digitStack.push(Integer.parseInt(item));
            }
            // 2.2 若item为运算符:出栈两个数字,根据item计算结果,并将结果入栈
            else {
                // (1) 设置计算数字和结果的int变量
                int number1 = digitStack.pop();
                int number2 = digitStack.pop();
                int result = 0;
                // (2) 计算结果
                switch (item) {
                    case "+":
                        result = number1 + number2;
                        break;
                    case "-":
                        result = number2 - number1;
                        break;
                    case "*":
                        result = number1 * number2;
                        break;
                    case "/":
                        result = number2 / number1;
                        break;
                    default:
                        throw new RuntimeException("wrong char");
                }
                // (3) 结果入栈
                digitStack.push(result);
            }
        }
        // 3. 返回栈顶数字
        return digitStack.pop();
    }

    /**
     * @author monash
     * ** 生成并获取表达式的"后缀表达式"(所输入的表达式已用括号标明了优先级)**
     * 思路:
     *      1. 创建一个空堆栈,opstack用于保留运算符。创建一个空列表进行输出。
     *      2. 使用string方法将输入的中缀字符串转换为列表 split。
     *      3. 从左到右扫描令牌列表。
     *          3.1 如果令牌是操作数,则将其附加到输出列表的末尾。
     *          3.2 如果标记是左括号,请将其推到上opstack。
     *          3.3 如果标记是右括号,请弹出opstack直到删除相应的左括号。将每个运算符追加到输出列表的末尾。
     *          3.4 如果令牌是*,/,+或-运算符,则将其推入 opstack。但是,请先删除上opstack具有更高或相等优先级的所有运算符 ,然后将它们附加到输出列表中。
     *      4. 将字符栈中剩余字符逐个出栈,并加入输出 list,返回输出list
     *
     * @param originalExpression - 原表达式,元素用空格隔开。如"( 7 * 4 ) - ( 20 / ( 3 + 1 ) )"
     * @return - 所生成的后缀表达式
     */
    public static ArrayList<String> getPostfixExpressionWithAllBracket(String originalExpression) {
        // 0. 校验参数:是否为null或者空
        originalExpression = originalExpression.trim();
        if (originalExpression == null || originalExpression.isEmpty()) {
            throw new RuntimeException("expression wrong");
        }

        // 1. 设置必要变量
        // 1.1 设置字符栈(stack<string>)
        Stack<String> operationStack = new Stack<>();
        // 1.2 设置输出list(list<string>)
        ArrayList<String> list = new ArrayList<>();

        // 2. 将originalExpression转化为string数组,遍历数组
        String[] originalArray = originalExpression.split(" ");
        for (String item : originalArray){
            // 2.1 若是数字,加入输出list
            if (item.matches("\\d+")){
                list.add(item);
            }
            // 2.2 若是字符,进行判断:
            else {
                switch (item) {
                    // (1) 若是"(":入字符栈
                    case "(":
                        operationStack.push(item);
                        break;
                    // (2) 若是")":字符栈逐个出栈,逐个添加入输出list,直到遇到"("后停止,并从字符栈中删除"("
                    case ")":
                        while(true){
                            String topOperator = operationStack.pop();
                            if (topOperator.equals("(")) {
                                break;
                            }
                            list.add(topOperator);
                        }
                        break;
                    // (3) 若是运算符:
                    case "+":
                    case "-":
                    case "*":
                    case "/":
                        // (3.1) 逐个将"栈内优先级大于当前运算符的运算符"出栈,放入输出list
                        while (!operationStack.isEmpty() && getPriority(operationStack.peek()) > getPriority(item)) {
                            list.add(operationStack.pop());
                        }
                        // (3.2) 处理完成后,当前运算符入字符栈
                        operationStack.push(item);
                        break;
                    // (4) 否则,抛出异常
                    default:
                        throw new RuntimeException("wrong character");
                }
            }
        }

        // 3. 将字符栈中剩余字符逐个出栈,并加入输出list,返回输出list
        while (!operationStack.isEmpty()) {
            list.add(operationStack.pop());
        }

        return list;
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值