1.先将中缀表达式转为后缀表达式
//中缀表达式转后缀表达式
public class Infix2Postfix {
public static void main(String[] args) {
String s = "1+((22+33)*4-5";
List<String> list = in2List(s);
System.out.println(list);
/*String str = "1 + ( ( 2 + 3 ) * 4 ) - 5";
String s = in2post(str);
System.out.println(s);*/
}
//中缀表达式转List
public static List<String> in2List(String str) {
int index = 0;
List<String> list = new ArrayList<>();
while (index < str.length()) {
Character c = str.charAt(index);
if (c < 48 || c > 57) {
//说明不是数
list.add(c.toString());
index++;
} else {
//是数字
String s = c.toString();
while (true) {
if (index == str.length() - 1 || str.charAt(index + 1) < 48 || str.charAt(index + 1) > 57) {
//到了最后一位或者下一位不是数字,放入集合中
list.add(s);
index++;
break;
} else {
s += str.charAt(index);
index++;
}
}
}
}
return list;
}
//中缀表达式转后缀表达式
public static String in2post(String str) {
//1+(2+3)*4-5 -> 1 2 3 + 4 * + 5 -
String[] strArr = str.split(" ");
//存放数和运算符(可以直接使用list代替,因为代码中没有pop操作,而且最后还需要逆序)
Stack<String> numStack = new Stack<>();
//临时存放运算符
Stack<String> opeStack = new Stack<>();
for (String s : strArr) {
if (s.matches("\\d+")) {
//若是数则直接放入,numStack
numStack.push(s);
} else {
switch (s) {
case "+":
case "-":
case "*":
case "/":
if (opeStack.isEmpty() || opeStack.peek().equals("(")) {
//若栈中没有其他符号,或前一个符号是“(”,直接入栈
opeStack.push(s);
} else {
//和ope栈中的每个运算符比较,直到比其优先级高,或者栈为空时入栈
while (true) {
if (opeStack.isEmpty()) {
//为空,说明已经和所有的栈中运算符进行了比较
opeStack.push(s);
break;
}
if (getPriority(s) > getPriority(opeStack.peek())) {
//优先级大于栈顶运算符,入栈-->入栈后结束循环
opeStack.push(s);
break;
} else {
//优先级小,将ope中的运算符,弹出压入num中
String pop = opeStack.pop();
numStack.push(pop);
}
}
}
break;
case "(":
opeStack.push(s);
break;
case ")":
//若为右括号
while (true) {
String pop = opeStack.pop();
if ("(".equals(pop)) {
//一直到左括号结束
break;
}
//将()期间的符号都弹出,压入num中
numStack.push(pop);
}
break;
}
}
}
while (!opeStack.isEmpty()) {
String pop = opeStack.pop();
numStack.push(pop);
}
StringBuilder sb = new StringBuilder();
List<String> list = new ArrayList<>();
while (!numStack.isEmpty()) {
String pop = numStack.pop();
list.add(pop);
}
for (int i = list.size() - 1; i >= 0; i--) {
sb.append(list.get(i));
if (i != 0) {
sb.append(" ");
}
}
return sb.toString();
}
//获取优先级
public static int getPriority(String str) {
int priority = 0;
switch (str) {
case "+":
case "-":
priority = 1;
break;
case "*":
case "/":
priority = 2;
break;
default:
break; }
return priority;
}
}
2.使用后缀表达式实现计算操作
//逆波兰实现计算器
public class PolandNotation {
public static void main(String[] args) {
//3 * 5 - 8 + 2 * 2 --> 3 5 * 8 - 2 2 * +
String reStr = "3 * 5 - 8 + 2 * 2";
//逆波兰表达式
String str = "3 5 * 8 - 2 2 * +";
//转换为数组
String[] strArr = str.split(" ");
int res = col(strArr);
System.out.printf("%s的运算结果为:%d", reStr, res);
}
//运算
public static int col(String[] strArr) {
Stack<String> stack = new Stack<>();
int res = 0;
for (String str : strArr) {
//若是一个数,直接压入栈中
if (str.matches("\\d+")) {
stack.push(str);
} else {
//若是一个符号,进行计算
//栈顶数
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
switch (str) {
case "+":
res = num1 + num2;
break;
case "-":
res = num2 - num1;
break;
case "*":
res = num1 * num2;
break;
case "/":
res = num2 / num1;
break;
default:
throw new RuntimeException("符号错误");
}
//将结果压入栈中
stack.push("" + res);
}
}
return Integer.parseInt(stack.pop());
}
}
从B站韩顺平老师的Java数据结构与算法习得。