中缀表达式转后缀表达式+逆波兰计算器实现

 

前言

java 菜鸟,正在学习java数据结构与算法;

根据中缀表达式转后缀表达式的规则、后缀表达式计算(逆波兰表达式)的规则,代码进行了实现。

有不当之处,还请提出改正


public class 逆波兰计算器 {

    public static void main(String[] args) {
        String str = "231 + 30*4 + (50 * 6 + 71) / 8";
        String resultString = stringToPolandNotation(str);
        System.out.println("resultString = " + resultString);
        //resultString = 231 30 4 * + 50 6 * 71 + 8 / +
        int resultNum = polandCaculator(resultString);
        System.out.println("resultNum = " + resultNum);
        //resultNum = 397
    }

    /**
     * 从左至右扫描表达式,遇到数字的时候,将数字压入堆栈;
     * 遇到运算符的时候,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素和栈顶元素),并将结果入栈;
     * 重复 上述过程直到表达式最右端,最后运算得出的值即为表达式的结果;
     *
     * @param str 逆波兰表达式字符串
     * @return
     */
    private static int polandCaculator(String str) {
        Stack<Integer> numStack = new Stack<>();
        int result = Integer.MIN_VALUE;
        int num = Integer.MIN_VALUE;
        for (int i = 0; i < str.length(); i++) {
            char operChar = str.charAt(i);
            if (i == str.length() - 1) {
                if (isOper(operChar)) {
                    int num1 = numStack.pop();
                    int num2 = numStack.pop();
                    result = calculate(num1, num2, operChar);
                }
            } else {
                if (operChar != ' ') {
                    if (isNumber(operChar)) {
                        if (num == Integer.MIN_VALUE) {
                            num = operChar - '0';
                        } else {
                            num = num * 10 + operChar - '0';
                        }
                    }
                    if (isOper(operChar)) {
                        int num1 = numStack.pop();
                        int num2 = numStack.pop();
                        int tempResult = calculate(num1, num2, operChar);
                        numStack.push(tempResult);
                    }
                } else {
                    if (num != Integer.MIN_VALUE) {
                        numStack.push(num);
                        num = Integer.MIN_VALUE;
                    }
                }
            }
        }
        return result;
    }

    private static int calculate(int num1, int num2, char operChar) {
        if (operChar == '+') return num1 + num2;
        if (operChar == '-') return num2 - num1;
        if (operChar == '*') return num1 * num2;
        if (operChar == '/') return num2 / num1;
        return 0;
    }

    /**
     * 中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。
     * 转换过程需要用到栈,具体过程如下:
     * 1. 如果遇到操作数,我们就直接将其输出。
     * 2. 如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
     * 3. 如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
     * 4. 如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。
     * 弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
     * 5. 如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
     *
     * @param str 需要转换的中缀表达式
     */
    private static String stringToPolandNotation(String str) {
        StringBuilder builder = new StringBuilder();
        Stack<Character> charStack = new Stack<>();
        int num = Integer.MIN_VALUE;
        for (int i = 0; i < str.length(); i++) {
            char operChar = str.charAt(i);
            if (i == str.length() - 1) {
                if (isNumber(operChar)) {
                    builder.append(operChar).append(" ");
                } else {
                    if (num != Integer.MIN_VALUE) {
                        builder.append(num).append(" ");
                        num = Integer.MIN_VALUE;
                    }
                }
                while (!charStack.isEmpty()) {
                    builder.append(charStack.pop()).append(" ");
                }
            } else {
                if (operChar != ' ') {

                    if (isNumber(operChar)) {
                        if (num == Integer.MIN_VALUE) {
                            num = operChar - '0';
                        } else {
                            num = num * 10 + operChar - '0';
                        }
                    }

                    if (isOper(operChar)) {
                        if (num != Integer.MIN_VALUE) {
                            builder.append(num).append(" ");
                            num = Integer.MIN_VALUE;
                        }
                        if (charStack.isEmpty()) {
                            charStack.push(operChar);
                        } else {
                            if (operChar == ')') {
                                while (charStack.size() != 0 && charStack.get(charStack.size() - 1) != '(') {
                                    builder.append(charStack.pop()).append(" ");
                                }
                                if (charStack.size() != 0 && charStack.get(charStack.size() - 1) == '(') {
                                    charStack.pop();
                                }
                            } else if (operChar == '(') {
                                charStack.push(operChar);
                            } else if (getPriority(charStack.get(charStack.size() - 1)) < getPriority(operChar)) {
                                charStack.push(operChar);
                            } else {
                                while (charStack.size() != 0 && getPriority(charStack.get(charStack.size() - 1)) >= getPriority(operChar)
                                        && charStack.get(charStack.size() - 1) != '(') {
                                    builder.append(charStack.pop()).append(" ");
                                }
                                charStack.push(operChar);
                            }
                        }
                    }
                }
            }
        }
        return builder.toString().trim();
    }

    private static int getPriority(char c) {
        if (c == '+' || c == '-') return 1;
        if (c == '*' || c == '/') return 2;
        if (c == '(' || c == ')') return 3;
        return Integer.MIN_VALUE;
    }

    private static boolean isNumber(char c) {
        return c >= '0' && c <= '9';
    }

    private static boolean isOper(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值