表达式一共有前缀表达式(比较不常用)、中缀表达式(最为普及的)、后缀表达式三种方法,可以通过表达式树来构建三种不同的表达式,表达式树是一种二叉树,其构成是由操作数和操作符构成,其中叶子节点全部为操作数,其余节点为操作符。根据对其的遍历方法不同就会得到三种不同的表达式:
下面三幅图代表了我们在一课二叉树中是如何实现三种遍历的,请注意对应遍历方法的颜色。
(图片来自 南京大学2020届软件学院离散数学课程,若有侵权请联系删除)



For example:
转换为后缀表达式即为
其中,中缀表达式和后缀表达式是两种较为常见的表达式,使用后缀表达式的原因是我们不需要知道其中操作符的优先级顺序,也不需要括号来辅助。这两种表达式也是计算机学科中较为常用的表达式。从后缀表达式转为中缀表达式的方法较为简单,本篇不做讨论。本篇文章旨在分享如何从中缀表达式变为后缀表达式的算法思想。
要将中缀表达式转换为后缀表达式,我们需要借助数据结构栈来处理,与此同时我们还需要一个地方来存储我们的输出(下面简称为输出)。然后我们根据以下的规则来遍历中缀表达式:
在这个算法中,"("的优先级是最高的,其次是"*"、"/",然后是"+"、"-"
下面我们来看具体的算法
package nju.edu.com;
import java.util.Deque;
import java.util.LinkedList;
/**
* @algorithm 从中缀表达式变成后缀表达式
* @author Zyi
* @create 2021/8/31 22:50
*/
@SuppressWarnings("JavaDoc")
public class Transfer {
/**
* 用deque来模拟栈
*/
private Deque<Character> stack = new LinkedList<>();
public int getPriority(char character) {
int priority = 0;
switch (character) {
case '+':
case '-':
priority = 2;
break;
case '*':
case '/':
priority = 3;
break;
case '(':
priority = 4;
break;
case ')':
priority = 5;
break;
default:
}
return priority;
}
public String transfer(String infix) {
StringBuilder postfix = new StringBuilder();
char[] characters = infix.toCharArray();
for (char character : characters) {
if (Character.isLetter(character) || Character.isDigit(character)) {
postfix.append(character);
} else {
if (character == ')') {
while (stack.peek() != '(') {
postfix.append(stack.pop());
}
// 移除左括号
stack.pop();
} else {
int currentPriority = getPriority(character);
while (true) {
if (stack.isEmpty()) {
stack.addFirst(character);
break;
} else {
if (getPriority(stack.peek()) >= currentPriority && stack.peek() != '(') {
postfix.append(stack.pop());
} else {
stack.addFirst(character);
break;
}
}
}
}
}
}
while (!stack.isEmpty()) {
postfix.append(stack.pop());
}
return postfix.toString();
}
}算法分析:
Deque双端队列来模拟栈,当然我们也可以选择数组、链表来模拟。getPriority(char character)用来获取当前操作符的优先级中缀表达式转后缀表达式可以说是栈的一种非常常见的应用。对我们理解栈这种结构有着很好的帮助。