动态数组栈的应用----后缀表达式的计算

本文介绍如何将中缀表达式转换为后缀表达式(逆波兰表达式),并通过一个具体的例子展示了整个转换过程及计算步骤。文章还提供了一个Java实现的方法来完成这一转换,并解释了计算后缀表达式的算法。

计算后缀表达式我们首先要将中缀表达式转换成后缀表达式,后缀表达式也叫逆波兰表达式,即将运算符写在操作数之后,如:

 1. 将中缀表达式转换成后缀表达式:

//将中缀表达式转换成后缀表达式
public class InfixToSuffix {
    public static void main(String[] args) {
        String expression = "(10+20/2*3)/2+8";
        expression = infixToSuffix(expression);
        System.out.println(expression);
    }

    //将中缀表达式转换成后缀表达式
    public static String infixToSuffix(String expression) {
        ArrayStack<String> operatorStack = new ArrayStack<>(); //字符栈 只存放字符
        ArrayList<String> suffixList = new ArrayList<>();
        expression = insertBlanks(expression); //按照指定格式格式化字符串
        String[] tokens = expression.split(" "); //按照“ ”分割字符串
        for(String token : tokens){
            if(token == null){
                continue;
            }
            if(isOperator(token)){
                /*
                1.栈为空时
                2.栈顶元素时 “(”
                3.当栈顶元素是操作符 且栈顶操作符的优先级 小于 当前token
                如果满足以上三个条件中的一个 就将当前字符token添加到字符栈operatorStack中
                如果栈顶元素操作符的优先级 大于等于 当前token 就将字符栈中的栈顶字符弹出并添加到列表suffixList中
                 */
                while (true){
                    if(operatorStack.isEmpty() || operatorStack.peek().equals("(") ||
                            priority(operatorStack.peek()) < priority(token)){
                        operatorStack.push(token);
                        break;
                    }
                    suffixList.add(operatorStack.pop());
                }
            }else if(token.equals("(")){ //如果当前字符是"("就直接将字符压入字符栈中
                operatorStack.push(token);
            }else if(token.equals(")")){ //如果当前字符是")" 就将字符栈中的所有栈顶元素都依次弹出并添加到列表suffixList中 直到栈顶字符是"("
                while (!operatorStack.peek().equals("(")){
                    suffixList.add(operatorStack.pop());
                }
                operatorStack.pop();
            }else if(isNumber(token)){ //如果当前字符是数字字符 就直接将数字字符添加到列表suffixList中
                suffixList.add(token);
            }
        }
        //遍历完字符串后 字符栈中还会有操作符
        //将字符栈中剩余的操作符全都依次弹出并添加到suffixList中
        while (!operatorStack.isEmpty()){
            suffixList.add(operatorStack.pop());
        }

        StringBuilder str = new StringBuilder();
        for(int i = 0; i < suffixList.size(); i++){
            str.append(suffixList.get(i));
            str.append(' ');
        }
        return str.toString();
    }

    //判断操作符的优先级
    //"-" "+"的优先级设为0  "*" "/"的优先级设为1
    private static int priority(String token) {
        if(token.equals("+") || token.equals("-")){
            return 0;
        }else if(token.equals("*") || token.equals("/")){
            return 1;
        }
        return -1;
    }

    //判断当前token字符是否是操作符
    private static boolean isOperator(String token) {
        return token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/");
    }

    //判断当前token字符是否是数字字符
    private static boolean isNumber(String token) {
        return token.matches("\\d+"); //正则表达式 \d表示匹配数字 +表示匹配多个
    }

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

2. 将中缀表达式转换成后缀表达式之后,就可以计算后缀表达式啦

//计算后缀表达式
public class SuffixCalculator {
    public static void main(String[] args) {
        String expression = "(10+20/2*3)/2+8";
        String suffixExpression = InfixToSuffix.infixToSuffix(expression);
        int result = evaluateExpression(suffixExpression);
        System.out.println(result);
    }

    //计算后缀表达式
    //只需要一个数字栈 遍历后缀表达式 如果遇到操作符 直接从数字栈中弹出两个数字进行运算
    //最后将运算结果压入数字栈即可

    private static int evaluateExpression(String suffixExpression) {
        String[] tokens = suffixExpression.split(" ");
        ArrayStack<Integer> numberStack = new ArrayStack<>();
        for(String token : tokens){
            if(token == null){
                continue;
            }else if(isNumber(token)){
                numberStack.push(Integer.parseInt(token));
            }else{
                processAnOperator(numberStack, token);
            }
        }
        return numberStack.pop();
    }

    //判断字符串token是否是数字字符串
    private static boolean isNumber(String token){
        return token.matches("\\d+"); //正则表达式 \d表示匹配数字 +表示匹配多个
    }

    //按照指定格式格式化字符串
    private static void processAnOperator(ArrayStack<Integer> numberStack, String token) {
        int num1 = numberStack.pop();
        int num2 = numberStack.pop();
        if(token.equals("+")){
            numberStack.push(num2 + num1);
        }else if(token.equals("-")){
            numberStack.push(num2 - num1);
        }else if(token.equals("*")){
            numberStack.push(num2 * num1);
        }else if(token.equals("/")){
            numberStack.push(num2 / num1);
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值