中缀表达式转换为后缀表达式(Java实现)

      我们把平时所用的标准四则运算表达式,即“9+(3-1)*3+10/2"叫做中缀表达式。后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。
在程序实现上,后缀表达式更易于实现,所以这里就看一下中缀表达式怎么转换为后缀表达式。
规则如下:

首先定义两个数据结构:

  • 一个字符StringBuilder,存放后缀表达式的结果
  • 一个栈,存放操作符

然后把中缀表达式当作一个字符串,表达式从左到右一个个字符判断,规则如下:

  • A. 如果是数字,直接存进StringBuilder

  • B. 如果字符是±* /( , 加减乘除和左括号

    • 1.栈为空,直接将操作符入栈
    • 2.假设现在的操作符是c,栈顶的操作符是s
      • c的优先级大于s,直接入栈;
      • c的优先级小于等于s,弹出s; 回到2.再重新进行判断,直到条件a满足;
        如果栈一直弹出,到栈空了,满足条件1.则将c入栈;
      • 如果栈顶元素是(,则直接入栈
  • C.如果字符是) , 右括号

    • 依次将栈顶元素添加进StringBuilder,直到遇到左括号
    • 左括号不加进StringBuilder,直接丢弃(此时右括号也不要了)
  • D.字符判断完了之后,如果栈不为空,则依次输出栈的元素到StringBuilder

四则运算优先级:

  • 加和减 1
  • 乘和除 2
  • ( 左括号 3
  • ) 右括号 4

注1:这里代码暂时没有考虑数字是小数的情况,后续加上
注2:如何根据后缀表达式计算结果,可以看我的下一篇 根据后缀表达式计算结果

中缀表达式转换为后缀表达式的Java代码如下:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) {
        System.out.println(calcu("3+4*5+(6*7+8)*9"));
       // 结果是: 345*+67*8+9*+
    }

    // 中缀表达式转换为后缀表达式
    public static String calcu(String s ) {
        Stack<Character> stack = new Stack<>();

        Pattern p = Pattern.compile("\\d");
        StringBuilder result = new StringBuilder();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            Matcher m = p.matcher(c+"");

            // 数字的话直接输出
            if (m.find()) {
                result.append(c+"");
//                System.out.println(c);
                continue;
            }

            /*  一个字符StringBuilder,存放后缀表达式的结果
                一个栈,存放操作符
               表达式从左到右一个个字符判断,规则如下:
               A. 如果是数字,直接存进StringBuilder
               B. 如果字符是+-* /( , 加减乘除和左括号
                    1. 栈为空,直接将操作符入栈
                    2. 假设现在的操作符是c,栈顶的操作符是s
                        a. c的优先级大于s,直接入栈;
                        b. c的优先级小于等于s,弹出s; 回到2.再重新进行判断,直到条件a满足
                            如果栈一直弹出,到栈空了,满足条件1.则将c入栈;
                        c. 如果栈顶元素是(,则直接入栈
               C. 如果字符是) , 右括号
                    1. 依次将栈顶元素添加进StringBuilder,直到遇到左括号
                    2. 左括号不加进StringBuilder,直接丢弃(此时右括号也不要了)
               D. 字符判断完了之后,如果栈不为空,则依次输出栈的元素到StringBuilder
            */
            if (c == '+' || c == '-' || c == '*'
                    || c == '/' || c == '(') {
                if (stack.isEmpty()) {
                    stack.push(c);
                    continue;
                } else {
                    boolean flag = true;
                    while (flag) {
                        if (stack.isEmpty() || conLevel(c) > conLevel(stack.peek()) || stack.peek() == '(') {
                            stack.push(c);
                            flag = false;
                            continue;
                        }

                        if (conLevel(c) <= conLevel(stack.peek())) {
//                            System.out.println(stack.pop());
                            result.append(stack.pop());
                        }
                    }
                }
            }
            if (c == ')') {
                while (stack.peek() != '(') {

//                    System.out.println(stack.pop());
                    result.append(stack.pop());
                }
                stack.pop();  // 左括号不要输出,只弹出
                continue;
            }
        }
        // 最后栈不为空,全部弹出并输出
        while (!stack.isEmpty()){
//            System.out.println(stack.pop());
            result.append(stack.pop());
        }

        return result.toString();
    }

    // 判断字符优先级
    public static int conLevel (char c) {
        int i = 0;
        switch (c) {
            case '+' :
                i = 1;
                break;
            case '-' :
                i = 1;
                break;
            case '*' :
                i = 2;
                break;
            case '/' :
                i = 2;
                break;
            case '(' :
                i = 3;
                break;
            case ')' :
                i = 0;
                break;
            default: i = -1;
        }
        return i;
    }
}

参考: http://www.nowamagic.net/librarys/veda/detail/2307
https://www.cnblogs.com/zhengxunjie/p/10372329.html

你可能感兴趣的:(练习题)