前言
前缀表达式:就是我们常见的算术表达式,这里就以1+((2+3))*5)-5举例。
后缀表达式:上面式子对应的后缀表达式为 1 2 3 + 5 * + 5 - 不难看出后缀表达式没有括号,而真因后缀表达式的这个形式,很好的贴合了计算机底层的运算原理(栈)
一、转换思路
1、初始化一个队列suffixList(用于存放最终的后缀表达式), 初始化一个栈stringStack(用于存放运算符)
2、从左至右遍历中缀表达式
3、遇到运算数,压入suffixList中
4、遇到运算符,压入stringStack中
1)若stringStack栈为空,或stringStack栈顶元素为“(”,则直接压入stringStack栈
2)否则,若运算符优先级高于栈顶元素,直接压入栈
3)否则,将stringStack栈顶元素弹出,压入到suffixList中,回到第4步重新比较
5、遇到括号“(”或“)”
1)若为“(”,则直接压入stringStack栈
2)若为“)”,则依次弹出stringStack中的运算符,压入suffixList中,直到遇到“(”为止,然后移除“(” 注意:这里是直接在stringStack中移除“(”!
6、遍历完毕后,将stringStack中剩余的元素依次弹出并压入到suffixList中,遍历输出队列suffixList即为算数表达式对应的后缀表达式(逆波兰表达式)
二、图片演示
三、代码实现
1、核心代码
代码如下(示例):
//将中缀表达式转化为后缀表达式
public static List<String> parseSuffixExpressionList(List<String> infixList) {
// Stack<String> numberStack = new Stack<>(); //存放需计算的数字 (在整个过程中一直在进栈, 最终也是将这个栈放到一个ArrayList中 故可直接新建一个List 如下
ArrayList<String> suffixList = new ArrayList<>();
Stack<String> stringStack = new Stack<>(); //存放运算符号
for (String s : infixList) {
if (s.matches("\\d+")) { //正则表达式 匹配到是多位数
suffixList.add(s);
} else if (s.equals("(")) {
stringStack.push(s);
} else if (s.equals(")")) {
while (!stringStack.peek().equals("(")) { //peek() 方法 查看栈顶元素 但不移除
suffixList.add(stringStack.pop()); //符号栈中弹出运算符加到list中 直到遇到符号(
}
stringStack.pop(); //将”(“ 弹出 消除括号
} else {
//当s的优先级小于stringStack栈顶的优先级 将stringStack栈顶的元素弹出并加入到suffixList中
if (stringStack.size() > 0 && Operation.getValue(stringStack.peek()) >= Operation.getValue(s)) {
suffixList.add(stringStack.pop());
}
stringStack.push(s); //将s压入栈
}
}
//将stringStack中剩余的运算符一次弹出并加入到suffixList中
while (stringStack.size() != 0) {
suffixList.add(stringStack.pop());
}
return suffixList; //放到List中 即为顺序输出 (若开始时创建的是两条栈, 则最终应该反转)
}
2.完整代码
代码如下(示例):
package com.xx.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @author 谢鑫
* @version 1.0
*/
public class InfixToSuffix {
public static void main(String[] args) {
String infixExpression = "1 + ( ( 2 + 3 ) * 5 ) - 5";
List<String> infixList = getListString(infixExpression); //将中缀表达式放到list中
System.out.println("中缀表达式对应的List");
System.out.println(infixList);
System.out.println("后缀表达式对应的List");
List<String> suffixList = parseSuffixExpressionList(infixList);
System.out.println(suffixList);
}
//将中缀表达式放到ArrayList中
public static List<String> getListString(String infixExpression) {
//将suffixExpression分割
String[] split = infixExpression.split(" ");
List<String> list = new ArrayList<>();
for (String element : split) { ;
list.add(element);
}
return list;
}
//将中缀表达式转化为后缀表达式
public static List<String> parseSuffixExpressionList(List<String> infixList) {
// Stack<String> numberStack = new Stack<>(); //存放需计算的数字 (在整个过程中一直在进栈, 最终也是将这个栈放到一个ArrayList中 故可直接新建一个List 如下
ArrayList<String> suffixList = new ArrayList<>();
Stack<String> stringStack = new Stack<>(); //存放运算符号
for (String s : infixList) {
if (s.matches("\\d+")) { //正则表达式 匹配到是多位数
suffixList.add(s);
} else if (s.equals("(")) {
stringStack.push(s);
} else if (s.equals(")")) {
while (!stringStack.peek().equals("(")) { //peek() 方法 查看栈顶元素 但不移除
suffixList.add(stringStack.pop()); //符号栈中弹出运算符加到list中 直到遇到符号(
}
stringStack.pop(); //将”(“ 弹出 消除括号
} else {
//当s的优先级小于stringStack栈顶的优先级 将stringStack栈顶的元素弹出并加入到suffixList中
if (stringStack.size() > 0 && Operation.getValue(stringStack.peek()) >= Operation.getValue(s)) {
suffixList.add(stringStack.pop());
}
stringStack.push(s); //将s压入栈
}
}
//将stringStack中剩余的运算符一次弹出并加入到suffixList中
while (stringStack.size() != 0) {
suffixList.add(stringStack.pop());
}
return suffixList; //放到List中 即为顺序输出 (若开始时创建的是两条栈, 则最终应该反转)
}
}
class Operation {
private static int ADD = 1;
private static int SUB = 1;
private static int MUL = 2;
private static int DIV = 2;
public static int getValue(String operation) {
int result = 0;
switch (operation) {
case "+":
result = ADD;
break;
case "-":
result = SUB;
break;
case "*":
result = MUL;
break;
case "/":
result = DIV;
break;
default:
System.out.println("出发处理该运算符!");
break;
}
return result;
}
}
总结
望纠正!