数据结构与算法(五)逆波兰(后缀表达式)计算器的简单实现

中缀转后缀表达式思路

新建一个栈辅助转换表达式
遍历中缀表达式:

  1. 如果是数字直接加入表达式尾端
  2. 遇到括号时:
    (1)左括号:将左括号压入栈中,继续遍历
    (2)右括号:将栈中遇到左括号之前的符号依次添加到表达式尾端。最后pop出该左括号,继续遍历。
  3. 遇到操作符时:
    (1)如果栈顶操作符为左括号,或者栈中没有元素则直接压入该操作符,继续遍历
    (2)如果操作符优先级高于栈顶操作符,直接压入该操作符,继续遍历
    (3)如果该操作符优先级低于或等于栈顶操作符,将栈顶操作符取出添加至表达式尾端,重复3。

当遍历完成后,记得将栈中剩余的操作符依次取出添加到表达式尾端。

import java.util.ArrayList;
import java.util.Stack;

public class ReversePolandCalculator {

    public static void main(String[] args) {
        String expression = "1+(30+5) * 2 - 8/4";

        ArrayList<String> infixExpression = toInfixExpression(expression);
        System.out.println("中缀表达式为:" + infixExpression);

        ArrayList<String> suffixExpression = toSuffixExpression(infixExpression);
        System.out.println("后缀表达式为:" + suffixExpression);

        System.out.println("计算结果为: " + reversePolandCalculate(suffixExpression));
    }

    private static int reversePolandCalculate(ArrayList<String> suffixExpression) {
        Stack<Integer> numStack = new Stack<>();
        for (String item : suffixExpression){
            //如果是数字,压入栈中
            if(item.matches("\\d+")){
                numStack.push(Integer.parseInt(item));
            }else{
                //如果是计算符号,则重栈中取出两个数据进行计算并将结果压入栈
                int num1 = numStack.pop();
                int num2 = numStack.pop();
                numStack.push(caculate(num1, num2, item));
            }
        }

        return numStack.pop();
    }

    private static int caculate(int num1, int num2, String operation) {
        switch (operation){
            case "+":
                return num2 + num1;
            case "-":
                return num2 - num1;
            case "*":
                return num2 * num1;
            case "/":
                return num2 / num1;
            default:
                throw new RuntimeException("Unknown operation" + operation);
        }
    }

    private static ArrayList<String> toSuffixExpression(ArrayList<String> infixExpression) {
        Stack<String> stack = new Stack<>();
        ArrayList<String> result = new ArrayList<>();
        for (String item : infixExpression){
            //如果是数字直接加入
            if(item.matches("\\d+")){
                result.add(item);
                continue;
            }

            //如果是左括号,压入栈,如果是右括号则将栈中数据一次加入数组,知道遇到左括号
            if(item.equals("(")){
                stack.push(item);
            }else if(item.equals(")")){
                while (!stack.peek().equals("(")){
                    result.add(stack.pop());
                }
                stack.pop();//弹出左括号
            }else {
                //压入的操作符优先级小于等于栈顶操作符
                while (!stack.isEmpty() && !stack.peek().equals("(") && operationPriority(item) <= operationPriority(stack.peek())){
                    result.add(stack.pop());
                }
                stack.push(item);
            }

        }
        //将栈中剩余的操作符加入数组
        while (!stack.isEmpty()){
            result.add(stack.pop());
        }
        return result;
    }

    private static int operationPriority(String operation){
        switch (operation){
            case "+":
                return 1;
            case "-":
                return 1;
            case "*":
                return 2;
            case "/":
                return 2;
            default:
                 throw new RuntimeException("Unknown operation" + operation);
        }
    }

    private static ArrayList<String> toInfixExpression(String expression) {
        char[] chs = expression.toCharArray();

        ArrayList<String> result = new ArrayList<String>();

        int length = chs.length;
        int index = 0;
        while(true){
            if(index == length){
                break;
            }
            if(chs[index] == ' '){
                index = index + 1;
                continue;
            }
            String str = new String("") + chs[index];

            if(str.matches("\\d+")){
                //考虑多位数
                while (true){
                    if(index + 1 == length){
                        break;
                    }
                    String character = "" + chs[++index];
                    if(character.matches("\\d+")){
                        str = str + character;
                    }else {
                        index--;
                        break;
                    }
                }
                result.add(str);
            }else{
                result.add(str);
            }
            index = index + 1;
        }


        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值