动态数组栈的应用----中缀计算器的实现

本文探讨了中缀表达式在计算中的应用,解释了中缀表达式不易于计算机直接解析但符合人类习惯的特点。通过举例‘(10+20/2*3)/2+8’,阐述了如何使用动态数组栈来实现中缀表达式的计算过程。

中缀表达式是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:10+5,与前缀表达式(例:* 5 10),或后缀表达式(例:5 10 -)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法。

与前缀或后缀记法不同的是,中缀记法中括号是必需的。

我们以" (10+20/2*3)/2+8 "这个中缀表达式为例来实现中缀计算器:

public class InfixCalculator {
    public static void main(String[] args) {
        String express = "(10+20/2*3)/2+8";
        int result = evaluateExpression(express);
        System.out.println(result);
    }

    //计算中缀表达式
    private static int evaluateExpression(String express) {
        express = insertBlanks(express); //按指定格式格式化字符串
        String[] tokens = express.split(" "); //将字符串以“ ”进行分割
        ArrayStack<Character> operatorStack = new ArrayStack<Character>(); //创建只存放运算符的栈
        ArrayStack<Integer> numberStack = new ArrayStack<Integer>(); //创建只存放数字的栈
        for (String token : tokens){
            if(token.length() == 0){ //过滤空串 如:“”
                continue;
            }else if(token.equals("+") || token.equals("-")){ //如果遍历到 + - 号
                while (!operatorStack.isEmpty() && (operatorStack.peek() == '+' ||
                        operatorStack.peek() == '-' ||
                        operatorStack.peek() == '*' ||
                        operatorStack.peek() == '/')){ //如果之前是别的+ - * / 则需要弹栈 并计算
                    processAnOperator(operatorStack, numberStack);
                }
                operatorStack.push(token.charAt(0)); //如果操作符栈为空 或者 不为空但栈顶为( 就将字符压入栈中
            }else if(token.equals("*") || token.equals("/")){ //如果遍历到 * / 号
                while (!operatorStack.isEmpty() && (operatorStack.peek() == '*' || operatorStack.peek() == '/')){ //如果之前是别的* / 则需要弹栈 并计算
                    processAnOperator(operatorStack, numberStack);
                }
                operatorStack.push(token.charAt(0)); //如果操作符栈为空 或者 不为空但栈顶为( 就将字符压入栈中
            }else if (token.equals(")")){//如果遍历到 )
                while (operatorStack.peek() != '('){ //只要操作符栈的栈顶不是左括号( 就挨个弹栈计算即可
                    processAnOperator(operatorStack, numberStack);
                }
                operatorStack.pop(); //最后 清掉左括号
            }else if (token.equals("(")){ //如果遍历到 (
                operatorStack.push(token.charAt(0)); //就直接将字符压栈
            }else{
                numberStack.push(Integer.parseInt(token)); //如果遍历到数字 就直接将数组压入数字栈
            }
        }
        while (!operatorStack.isEmpty()){ //处理最后面的操作符
            processAnOperator(operatorStack, numberStack);
        }
        return numberStack.pop(); //最后的结果就是数字栈最后的栈顶元素
    }

    //操作符栈弹栈一个元素 数字栈弹栈两个数字 进行计算 并将新的结果进栈到数字栈
    private static void processAnOperator(ArrayStack<Character> operatorStack, ArrayStack<Integer> numberStack) {
        char operator = operatorStack.pop(); //弹出字符栈中的一个字符
        int num1 = numberStack.pop(); //弹出数字栈中的第一个数组
        int num2 = numberStack.pop(); //弹出数字栈中的第二个数组
        //先弹出的数字应放在运算符右边运算 后弹出的数字应放在运算符左边运算
        //num2 operator num1
        if(operator == '+'){
            numberStack.push(num2 + num1 );
        }else if (operator == '-'){
            numberStack.push(num2 - num1);
        }else if(operator == '*'){
            numberStack.push(num2 * num1);
        }else{
            numberStack.push(num2 / num1);
        }
    }

    //对原表达式进行格式化处理 给所有的非数字字符两边添加空格
    //是表达式变为“ ( 10 + 20 / 2 * 3 )  / 2 + 8”
    private static String insertBlanks(String express) {
        StringBuilder newExpe = new StringBuilder();
        for(int i = 0; i < express.length(); i++){
            char c = express.charAt(i);
            if(c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/'){
                newExpe.append(' ');
                newExpe.append(c);
                newExpe.append(' ');
            }else{
                newExpe.append(c);
            }
        }
        return newExpe.toString();
    }
}

该表达式的运行结果为:

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值