实现代码如下,已有详细注释,后续再补概念。
package infix_to_suffix;
import com.sun.istack.internal.NotNull;
import com.sun.tools.javac.util.StringUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
/**
* @description: 中缀表达式转后缀表达式
* @author: shicaid
* @create: 2019-07-24 21:32
**/
public class InfixToSuffix {
/**
* 分隔号---用户美观输出后缀表达式
*/
private static final String DIVIDE_SYMBOL = " ";
public static void main(String[] args) {
// String infix = "9+(3-1)*3+10/2";
// String infix = "9+(3-1*2)*2+10/2";
// String infix = "9+(3-1*2+3)*3+10/2";
// String infix = "1 + (( 2 + 3)* 4 ) - 5";
// String infix = "(9+(3-1*2+1))*3+10/2";
String infix = "9+3/1*2/1*2";
// 避免中缀表达式中的空格影响
infix = infix.trim();
infix = infix.replaceAll(" ","");
// 中缀转后缀结果
String suffix = InfixToSuffix.transformSuffix(infix);
System.out.println(suffix);
// 计算后缀表达式结果
System.out.println("caculate:");
System.out.println(infix+"="+ caculate(suffix));
}
/**
* 中缀表达式转换后缀表达式
*
* @param infixExpression
* @return
*/
public static String transformSuffix(@NotNull String infixExpression) {
StringBuffer result = new StringBuffer();
// 将数字和符号分隔出来,数组存储
String[] infixStrs = splitInfixExpression(infixExpression);
// 辅助栈
Stack<String> stack = new Stack<>();
// begin
// 1、遍历中缀表达式的数组
for (String infixStr : infixStrs) {
// 2、遍历中,如果遇到数字,直接输出
if(isNumber(infixStr)){
// 加个空格美观一点
result.append(infixStr).append(DIVIDE_SYMBOL);
continue;
}
// 3、若不是数字,先判断是否是 ( , 是的话直接入栈
if(infixStr.equals("(")) {
stack.push(infixStr);
} else if(infixStr.equals(")")){
// 4、如果是 ),则将从栈顶向栈低遍历输出,遇到第一个 (,停止输出,( )这两个皆不输出
String top = stack.pop();
while (!top.equals("(")){
result.append(top).append(DIVIDE_SYMBOL);
top = stack.pop();
}
}else {
// 5、普通的+-*/符号,如果infixStr的优先级小于或等于栈顶的符号,则输出栈顶,
// 直到infixStr的优先级大于栈顶符号 或 遇到 ( ,infixStr入栈
if(stack.isEmpty()){
// 当然,可能为空栈
stack.push(infixStr);
} else{
// 不是空栈
String top = stack.peek();
while (!top.equals("(") && compareSymbolPriority(infixStr,top) <= 0){
// infixStr的优先级小于或等于栈顶的符号
result.append(top).append(DIVIDE_SYMBOL);
// top出栈
stack.pop();
// 检查栈
if(stack.isEmpty()){
top = null;
break;
}else {
// 获取下一个top的值
top = stack.peek();
}
}
// infixStr入栈
stack.push(infixStr);
}
}
}
// 6、将栈中剩余的全部出栈
while (!stack.isEmpty()){
String top = stack.pop();
result.append(top).append(DIVIDE_SYMBOL);
}
// end
return result.toString();
}
/**
* 拆分中缀表达式,将整个字符串转为数字符号分离的字符串数组
*
* 使得表达式不局限于 个位数 的 加减乘除
*
* @param infixExpression 9+(3-1)*3+10/2
* @return [9,+,(,3,-,1,),*,3,+,10,/,2]
*/
private static String[] splitInfixExpression(String infixExpression){
List<String> list = new ArrayList<>();
StringBuffer numer = new StringBuffer();
for (char c : infixExpression.toLowerCase().toCharArray()) {
if(isNumber(c+"")){
numer.append(c);
continue;
}
// 当不是数字时,输出上一个数字
String numberStr = numer.toString();
if(!numberStr.isEmpty()){
list.add(numberStr);
}
numer.delete(0,numer.length());
// 符号的话直接输出
list.add(c+"");
}
String numberStr = numer.toString();
if(!numberStr.isEmpty()){
list.add(numberStr);
}
return list.toArray(new String[]{});
}
/**
*
* @Description: 比较两个符号的优先级: / = * > - = +
* @Param:
* @return: >0 first > last;
* =0 first = last;
* <0 first < last;
* @Author: shicaid
* @Date: 2019-07-24
*/
private static int compareSymbolPriority(String first, String last) {
int firstNum = virturalSymbolNumber(first);
int lastNum = virturalSymbolNumber(last);
if(firstNum * lastNum == 0)
throw new IllegalArgumentException("argument("+first+","+last+") is illegal !");
return firstNum - lastNum;
}
/**
* 检查字符是否是数字
*
* @param s
* @return
*/
private static boolean isNumber(String s) {
if(s.length() > 1){
// 在此处,符号只有1位,所以大于1位的都是数字(int但不限于int,float自然仍不支持啦)
return true;
}
char c = s.charAt(0);
return c >= 48 && c <= 57;
}
/**
* 将符号转为虚拟数字
*
* @param c
* @return
*/
private static int virturalSymbolNumber(String c){
int result;
switch (c){
case "/":
result = 2;
break;
case "*":
result = 2;
break;
case "-":
result = 1;
break;
case "+":
result = 1;
break;
default:
result = 0;
break;
}
return result;
}
/**
* 计算后缀表达式的值
* @param suffixExpression
* @return
*/
public static int caculate(String suffixExpression){
Stack<String> numberStack = new Stack<>();
for (String s : suffixExpression.trim().split(DIVIDE_SYMBOL)) {
if(isNumber(s)){
numberStack.push(s);
continue;
} // 不是数字,是符号,计算啦
String top = numberStack.pop();
String second = numberStack.pop();
int topInt = Integer.valueOf(top);
int secondInt = Integer.valueOf(second);
int tempResult = 0;
switch (s){
case "/":
tempResult = secondInt / topInt;
break;
case "*":
tempResult = secondInt * topInt;
break;
case "-":
tempResult = secondInt - topInt;
break;
case "+":
tempResult = secondInt + topInt;
break;
default:
break;
}
// 最终结果入栈
numberStack.push(tempResult+"");
}
return Integer.valueOf(numberStack.pop());
}
}