中缀表达式转化为后缀表达式
报错:Exception in thread "main" java.util.EmptyStackException
at java.base/java.util.Stack.peek(Stack.java:102)
at java.base/java.util.Stack.pop(Stack.java:84)
at Stack.PolandNotation.parseSuffixExpressionList(PolandNotation.java:56)
at Stack.PolandNotation.main(PolandNotation.java:18)
好兄弟们帮我看看,为啥比着敲都报错啊,我已经看了两个小时了。。。
```java
package Stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
/*添加一个将中缀表达式转换成后缀表达式的功能:
1。因为直接对string进行操作不方便,因此将"1+((2+3)*4)-5" 转成中缀表达式对应的List
即 "1+((2+3)*4)-5" --> ArrayList [1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]*/
String expression = "1+((2+3)*4)-5";
List<String> List01 = toInfixExpressionList(expression);
System.out.println(List01);
/*2.将中缀表达式的List --> 后缀表达式的List
即 ArrayList [1, +, (, (, 2, +, 3, ), *, 4, ), -, 5] --> ArrayList[1, 2, 3, +, 4, *, +, 5, –]*/
List<String> List03 = parseSuffixExpressionList(List01);
System.out.println(List03);
/*先定义一个逆波兰表达式
(3+4)×5-6 对应的后缀表达式就是: 3 4 + 5 * 6 -
为了说明方便,逆波兰表达式的数字和符号用空格隔开*/
//String suffixExpression = "30 4 + 5 * 6 -";
/*IDEA:1、先把 "3 4 + 5 × 6 -" 放入ArrayList中 (为了不用一一扫描)
2、将ArrayList传递一个方法,遍历AL 再配合栈完成计算*/
//List<String> rpnList = getListString(suffixExpression);
//System.out.println("rpnList=" + rpnList);
// int res = calculate(rpnList);
//System.out.println("res=" + res);
}
//2.将中缀表达式的List --> 后缀表达式的List:
public static List<String> parseSuffixExpressionList(List<String> ls) {
Stack<String> s1 = new Stack<String>();//符号栈 s1
//由于s2没有pop操作,而且后面还有逆序输出,所以不用Stack<String>s1,改用List<String>
List<String> s2 = new ArrayList<String>();//储存中间结果List s2
for (String item : ls) {//遍历ls
if (item.matches("\\d+")) {// 1⃣️if num
s2.add(item);
} else if (item.equals("(")) {
s1.push(item);
} else if (item.equals(")")) {
/*如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,
直到遇到左括号为止,此时将这一对括号丢弃*/
while (s1.size() != 0 && !s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();//消除小括号
} else {//2⃣️ if operation
//当item优先级 <= peek优先级 将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;
while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
s2.add(s1.pop());
}
s1.push(item);//若优先级比栈顶运算符的高,将运算符压入s1;
}
}
//将最后s1剩余的运算符加入s2
while(s1.size() != 0){
s2.add(s1.pop());
}
return s2;//以为是存放进List,所以按顺序输出就是结果了
}
//1.将中缀表达式转成List的方法:
public static List<String> toInfixExpressionList(String s) {
List<String> ls = new ArrayList<String>();
int i = 0;//表示一个指针,用于遍历中缀里的字符串
String str;//多位数的拼接
char ch;//遍历到字符就放入ch
do {
if ((ch = s.charAt(i)) < 48 || (ch = s.charAt(i)) > 57) {//不是数字就加入ls
ls.add("" + ch);
i++;
} else {//如果是数字,还要判断是不是多位数
str = " ";//先清空一下字符串
while (i < s.length() && (ch = s.charAt(i)) >= 48 && (ch = s.charAt(i)) <= 57) {
str += ch;//拼接
i++;
}
ls.add(str);
}
} while (i < s.length());
return ls;
}
//将逆波兰表达式放入AL中
public static List<String> getListString(String suffixExpression) {
String[] split = suffixExpression.split(" ");//分割逆波兰
List<String> list = new ArrayList<String>();
for (String ele : split) {
list.add(ele);
}
return list;
}
/*逆波兰表达式求值步骤如下:
1.从左至右扫描(go through),将3和4压入堆栈;
2.遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
3.将5入栈;
4.接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
5.将6入栈;
6.最后是-运算符,计算出35-6的值,即29,由此得出最终结果 */
public static int calculate(List<String> ls) {
Stack<String> stack01 = new Stack<String>();//只需new一个stack
for (String item : ls) {//go through the list
//使用正则表达式来取数
if (item.matches("\\d+")) { //匹配的是多位数
stack01.push(item);//如果是是数就直接入栈
} else {//如果不是就pop两个数,运算后,再入栈
int num1 = Integer.parseInt(stack01.pop().trim());
int num2 = Integer.parseInt(stack01.pop().trim());
int res = 0;
if (item.equals("+")) {
res = num2 + num1;
} else if (item.equals("-")) {
res = num2 - num1;
} else if (item.equals("*")) {
res = num2 * num1;
} else if (item.equals("/")) {
res = num2 / num1;
} else {
throw new RuntimeException("运算符有误!");
}
//把res入栈
stack01.push(res + " ");//把int --》 char
}
}
//最后的res就是结果
return Integer.parseInt(stack01.pop());
}
}
//priority class
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("the operation doesn't exist!");
break;
}
return result;
}
}
```