1. 前缀表达式(波兰表达式)
-
例子:
(3+4)*5-6的前缀表达式是- * + 3 4 5 6 -
计算过程如下:从右至左扫描前缀表达式,遇到数字时,将数字压入栈,遇到运算符时,弹出栈顶的两个元素做运算,再将结果入栈。重复上述步骤,直到表达式最左端最后运算出结果。
2. 后缀表达式(逆波兰表达式)
- 例子:
(3+4)*5-6的后缀表达式是3 4 + 5 * 6 - - 计算过程如下:从左至右扫描后缀表达式,遇到数字时,将数字压入栈,遇到运算符时,弹出栈顶的两个元素做运算,再将结果入栈。重复上述步骤,直到表达式最右端最后运算出结果。(注意:遇到减号/除号时,是 次顶元素 减去/除去 栈顶元素)
2.1 计算算法
public static double calc(String postfixExpression, String separator) {
if (postfixExpression == null || separator == null) {
return 0;
}
Stack<Double> stack = new Stack<>();
for (String item : postfixExpression.split(separator)) {
// 匹配是数字
if (item.matches("\\d+")) {
stack.push(Double.valueOf(item));
} else {
Double num1 = stack.pop();
Double num2 = stack.pop();
double result;
switch (item) {
case "+": {
result = num2 + num1;
break;
}
case "-": {
result = num2 - num1;
break;
}
case "*": {
result = num2 * num1;
break;
}
case "/": {
result = num2 / num1;
break;
}
default: {
result = 0d;
break;
}
}
stack.push(result);
}
}
return stack.pop();
}
3. 中缀表达式转逆波兰表达式
3.1 思路步骤
1、初始化两个栈:运算符栈s1和存储中间结果的栈s2
2、从左至右扫描中缀表达式
3、如果遇到操作数时,将其压入s2
4、如果遇到运算符
4.1)如果s1为空,或者栈顶运算符为左括号"(",则直接将此运算符压入s1
4.2)否则,若该运算符的优先级比栈顶运算符的高,也将此运算符压入s1
4.3)否则,将s1栈顶的运算符弹出并压入s2,再回到步骤4.1继续比较
5、如果遇到括号
5.1)遇到的是左括号"(",则直接压入s1
5.2)遇到的是右括号")",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,将这对括号消除
6、重复步骤2-5,直到扫描完中缀表达式
7、将s1中剩余的运算符依次弹出并压入s2
8、将s2的元素依次弹出,其结果的逆序就是后缀表达式(整个过程s2可以用一个队列代替)
3.2 代码实现
public class PostfixExpression {
private static final Map<String, Integer> OPERATOR_MAP = new HashMap<String, Integer>() {
{
put("+", 0);
put("-", 1);
put("*", 2);
put("/", 3);
put("(", 4);
}
};
private static final int[][] OPERATOR_PRIORITY = new int[][]{
{0, 0, -1, -1, 1},
{0, 0, -1, -1, 1},
{1, 1, 0, 0, 1},
{1, 1, 0, 0, 1},
{-1, -1, -1, -1, 0}
};
public static void main(String[] args) {
String postfixExpression = getPostfixExpression("1+((2+3)*4)-5");
System.out.println(postfixExpression);
}
public static String getPostfixExpression(String infixExpression) {
return getPostfixExpression(infixExpression, " ");
}
/**
* 中缀表达式转换为逆波兰表达式
*/
public static String getPostfixExpression(String infixExpression, String separator) {
if (infixExpression == null || "".equals(infixExpression)) {
return "";
}
List<String> element = getElement(infixExpression);
Stack<String> operatorStack = new Stack<>();
List<String> result = new ArrayList<>();
for (String item : element) {
if (!isOperator(item)) {
result.add(item);
} else if ("(".equals(item)) {
operatorStack.push(item);
} else if (")".equals(item)) {
while (!"(".equals(operatorStack.peek())) {
result.add(operatorStack.pop());
}
operatorStack.pop();
} else {
while (operatorStack.size() != 0 && judgePriority(operatorStack.peek(), item) >= 0) {
result.add(operatorStack.pop());
}
operatorStack.push(item);
}
}
while (operatorStack.size() > 0) {
result.add(operatorStack.pop());
}
if (separator == null) {
separator = " ";
}
return String.join(separator, result);
}
private static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/'
|| c == '(' || c == ')';
}
private static boolean isOperator(String str) {
return "+".equals(str) || "-".equals(str) || "*".equals(str) || "/".equals(str)
|| "(".equals(str) || ")".equals(str);
}
private static List<String> getElement(String infixExpression) {
List<String> element = new ArrayList<>();
List<Character> operand = new ArrayList<>();
for (char c : infixExpression.toCharArray()) {
if (isOperator(c)) {
if (operand.size() > 0) {
element.add(getOperand(operand));
operand.clear();
}
element.add(String.valueOf(c));
} else {
operand.add(c);
}
}
if (operand.size() > 0) {
element.add(getOperand(operand));
operand.clear();
}
return element;
}
private static String getOperand(List<Character> operand) {
StringBuilder sb = new StringBuilder();
for (char c : operand) {
sb.append(c);
}
return sb.toString();
}
private static int judgePriority(String operator1, String operator2) {
int num1 = OPERATOR_MAP.getOrDefault(operator1, 0);
int num2 = OPERATOR_MAP.getOrDefault(operator2, 0);
return OPERATOR_PRIORITY[num1][num2];
}
}