后缀表达式和逆波兰计算器(Java)

功能

实现整数的复杂运算。如:((17+34)/3+6)*4

逆波兰表达式(后缀表达式)

  • 前缀表达式:从右到左扫描,先将所有数字压入堆栈。遇到运算符时,弹出栈顶的两个数,对栈顶元素和次顶元素进行运算,并将结果入栈。重复上述过程直到算完。 举例:(3+4)×5-6 = - × + 3 4 5 6

  • 中缀表达式:人类可以理解的算法

  • 后缀表达式:从左到右扫描,遇到数字直接压入栈,遇到运算符则弹出栈顶两个数进行运算并入栈,重复上述过程直到算完。逆波兰表达式,即后缀表达式。 举例:(3+4)×5-6 = 3 4 + 5 × 6

逆波兰计算器的实现思路

中缀表达式转后缀表达式

1.生成逆波兰表达式(中缀表达式转后缀表达式) 1.将中缀表达式写入List 2.需要两个栈,其一存储运算符(临时),其二存储表达式 1.从左到右扫描List,数字和左括号直接入栈; 右括号,依次弹出运算符并入栈,直到第一个左括号;(括号需消除) 比较运算符优先级, 若当前运算符比栈顶原算法优先级高,则直接压入 若低,则将栈顶运算符弹出,并压入表达式栈,进入下次大循环 2.将剩余运算符依次转入表达式栈

计算逆波兰表达式结果 将存有后缀表达式的list写入Stack。 从左往右扫描,遇到数字直接入栈; 遇到运算符,弹出栈顶两位元素,进行"次顶 运算符 栈顶"的运算,将结果压入栈顶 重复以上,直到算完

代码实现

class PolishNotationTest {
    public static void main(String[] args) {
        InversePolishCalculate polish = new InversePolishCalculate();
        String expression = "((17+34)/3+6)*4";
        List<String> infixExpression = polish.toInfixExpressionList(expression);
        System.out.println(infixExpression);//[(, (, 17, +, 34, ), /, 3, +, 6, ), *, 4]
        try {
            List<String> suffixExpression = polish.getSuffixExpression(infixExpression);
            System.out.println(suffixExpression);//[17, 34, +, 3, /, 6, +, 4, *]
            int result = polish.calculate(suffixExpression);
            System.out.println(result);//92
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class InversePolishCalculate {
    //将中缀表达式转为List
    public List<String> toInfixExpressionList(String s) {
        List<String> list = new ArrayList();
        String str;
        for(int i = 0; i < s.length();) {
            if(s.charAt(i) < 48 || s.charAt(i) > 57) {//非数字
                list.add(Character.toString(s.charAt(i)));
                i ++;
            }else {
                //考虑多位数
                str = "";
                while(i < s.length() && (s.charAt(i) >= 48 && s.charAt(i) <= 57)) {
                    str += s.charAt(i);
                    i ++;
                }
                list.add(str);
            }
        }
        return list;
    }

    //将中缀表达式list转为后缀表达式list
    public List<String> getSuffixExpression(List<String> list) {
        Stack<String> valueStack = new Stack<String>();//存放数字和符号
        Stack<String> tempStack = new Stack<String>();//存放运算符

        for(String ele : list) {
            if(ele.matches("\\d+")) {//数字直接入value栈
                valueStack.push(ele);
            }else if(ele.equals("(")) {//左括号直接入temp栈
                tempStack.push(ele);
            }else if(ele.equals(")")) {
                //遇到右括号,依次弹出tempStack中运算符直到遇到第一个左括号
                while(!tempStack.peek().equals("(")) {
                    valueStack.push(tempStack.pop());
                } tempStack.pop();//弹出括号
            }else {//判断运算符优先级并操作
                while(tempStack.size() != 0 && (operatorPriority(ele) <= operatorPriority(tempStack.peek()))) {
                    valueStack.push(tempStack.pop());
                } tempStack.push(ele);
            }
        }
        while(tempStack.size() != 0) {
            valueStack.push(tempStack.pop());
        }
        return valueStack;
    }

    //将逆波兰表达式放入List
    public List<String> getListString(String suffixExpression) {
        String[] split = suffixExpression.split(" ");
        List<String> list = new ArrayList<String>();
        for(String ele : split) {
            list.add(ele);
        }
        return list;
    }

    //计算逆波兰表达式结果
    public int calculate(List<String> list) {
        Stack<String> stack = new Stack<String>();//通过栈存取和运算
        for(String ele : list) {
            if(ele.matches("\\d+")) {//判断是否为数(多位数)
                stack.push(ele);
            }else {
                int v1 = Integer.parseInt(stack.pop());
                int v2 = Integer.parseInt(stack.pop());
                int result = 0;
                switch(ele) {
                    case "+":
                        result = v2 + v1;
                        break;
                    case "-":
                        result = v2 - v1;
                        break;
                    case "*":
                        result = v2 * v1;
                        break;
                    case "/":
                        result = v2 / v1;
                        break;
                    default:
                        throw new RuntimeException("运算符错误");
                }
                stack.push(Integer.toString(result));
            }
        }
        return Integer.parseInt(stack.pop());
    }

    public int operatorPriority(String operator) {
        int result = 0;
        if(operator.equals("+")) {
            result = 1;
        } else if(operator.equals("-")) {
            result = 1;
        } else if(operator.equals("*")) {
            result = 2;
        } else if(operator.equals("/")) {
            result = 2;
        } else if(operator.equals("(")) {//如果检测到"("符号,则停止循环
            result = -1;
        } else {
            throw new RuntimeException("接收的符号错误");
        }
        return result;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值