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

2,450 阅读2分钟

什么是中缀表达式?什么是后缀表达式?

  中缀表达式的操作符是以中缀形式处于操作数的中间,中缀表达式是人们常用的算术表示方法,例如:( 3 + 4 ) * 5 - 8 / 2

  后缀表达式也叫逆波兰式,就是形如3 4 + 5 * 8 2 / -的表达式:即运算符在操作数之后,除此以外还有前缀表达式:即运算符在操作数之前。

为什么要搞出中缀表达式和后缀表达式呢?

  因为中缀表达式便于我们的理解与计算,但是后缀表达式更方便计算机的运算(例如:二叉树、堆栈等),所以在读取一个中缀表达式后,我们将他转化为后缀表达式,然后交由计算机运算会更加方便。

中缀转后缀的实现思路

  • 首先需要定义两个栈分别为数值栈和符号栈
  • 对整个表达式进行分割得到每个操作数和运算符
  • 遍历分割得到的数组:
  1. 如果该串为数值,如果是则压入数值栈。
  2. 如果该串为),如果是则说明需要转化小括号内的数据,依次取出数值栈中为栈顶的两个元素和符号栈中的栈顶元素,进行拼接,中间以空格分割,然后压入数值栈。
  3. 如果该串为(,则直接将其压入符号栈。
  4. 如果该串为其他符号(+、-、*、/)时,判断如果符号栈不为空,则比较该栈顶符号和该符号的优先级,如果栈顶元素优先级高,则重复2中的转化拼接操作。如果符号栈为空则直接压入符号栈。
  5. 重复1、2、3、4步骤直至遍历结束。
  • 此时判断如果符号栈为空,则直接输出最终结果(即数值栈中的唯一元素),否则继续重复上述2的操作。

代码实现(java)

import java.util.Stack;

public class transform {
    public static void main(String[] args) {
        Stack<String> stack_value = new Stack<>();
        Stack<String> stack_symbol = new Stack<>();
        String expression = "( 3 + 4 ) * 5 - 8 / 2";
        String [] str = expression.split(" ");
        for (String s:str
             ) {
            if (isValue(s)) {
                stack_value.push(s);
            } else {
                if (s.equals(")")) {
                    Intermediate_results(stack_value, stack_symbol);
                    stack_symbol.pop();
                } else if (s.equals("(")) {
                    stack_symbol.push(s);
                } else {
                    if (!stack_symbol.isEmpty()) {
                        if (priority(s) <= priority(stack_symbol.peek())) {
                            Intermediate_results(stack_value, stack_symbol);
                        }
                    }
                    stack_symbol.push(s);
                }
            }
        }
        while (!stack_symbol.isEmpty()) {
            Intermediate_results(stack_value, stack_symbol);
        }
        System.out.println(stack_value.peek());
    }
    
    // 判断是否为数值,返回true为数值
    public static Boolean isValue (String s) {
        return !s.equals("+") && !s.equals("-") && !s.equals("*") && !s.equals("/") && !s.equals("(") && !s.equals(")");
    }
    
    // 计算各运算符的优先级
    public static int priority(String s) {
        int p = 0;
        switch (s) {
            case "+":
            case "-": {
                p = 1;
                break;
            }

            case "*":
            case "/": {
                p = 2;
                break;
            }
            case "(": {
                p = -1;
                break;
            }
        }
        return p;
    }

    // 对中间结果进行拼接、入栈等操作
    public static void Intermediate_results(Stack<String> stack_value, Stack<String> stack_symbol) {
        String res = "";
        String s2 = stack_value.pop();
        String s1 = stack_value.pop();
        res += s1 + " " + s2;
        res += " " + stack_symbol.pop();
        stack_value.push(res);
    }
}