数据结构之栈三 中缀表达式转后缀表达式
一、实现步骤
1.将计算的字符串转化为数组list,利于后续的遍历
2.定义一个栈s1用于存放运算符,定义一个数组s2用于存放后缀表达式
3.遍历list
- 数字:直接添加到s2数组中
- 运算符:
①:‘(’或者s1为空再或者是s1栈顶元素为’(’:直接入s1栈
②:‘)’依次将s1栈顶元素添加到s2数组中,直到栈顶元素是’(’,然后把‘(’出栈
③:运算符emp:比较该运算符emp和s1栈顶元素运算符优先级,如果s1不为空且优先级小于或等于栈顶元素,将s1栈顶元素添加到s2数组中,然后emp再次和s1栈顶元数比较,直到为空或者该运算符优先级大于s1栈顶元素,emp入栈。
4.将s1栈中的运算符依次加入到s2数组中,s2就是该中缀表达式的后缀表达式
二、代码实现
package demo.sjjg.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
//中缀表达式转换为后缀表达式
public class ZhongToHou {
public static void main(String[] args) {
String value = "30 + 4 * ( 2 + 3 ) - 8 / 4";//30 4 2 3 + * + 8 4 / - = 48
List<String> list = getListString(value);
Stack<String> s1 = new Stack<>();
List<String> s2 = new ArrayList<>();
for (String emp : list) {
if (emp.matches("\\d+")) {
//数字直接入数组
s2.add(emp);
} else if (emp.equals("(") || s1.empty() || s1.peek().equals("(")) {
//栈空、该符号为'('或者栈顶元素是'('
s1.push(emp);
} else if (emp.equals(")")) {
while (!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();// ‘(’ 出栈
} else {
//比较字符优先级
while (s1.size() != 0 && (per(emp) <= per(s1.peek()))) {
s2.add(s1.pop());
}
s1.push(emp);
}
}
while (s1.size() != 0) {
s2.add(s1.pop());
}
System.out.println(value+"的后缀表达式为:"+s2);
System.out.println(value+" = "+calculate(s2));
}
//将字符串转化为list数组利于遍历
private static List<String> getListString(String value) {
String[] s = value.split(" ");
ArrayList<String> list = new ArrayList<>();
for (String emp : s) {
list.add(emp);
}
return list;
}
//计算
private static int calculate(List<String> list) {
Stack<String> stack = new Stack<>();
for (String emp:list){
if (emp.matches("\\d+")){
stack.push(emp);
}else {
int num1= Integer.parseInt(stack.pop());
int num2= Integer.parseInt(stack.pop());
int res=0;
if (emp.equals("+")){
res=num1+num2;
}else if (emp.equals("-")){
res=num2-num1;
}else if (emp.equals("*")){
res=num2*num1;
}else if (emp.equals("/")){
res=num2/num1;
}
stack.push(""+res);
}
}
return Integer.parseInt(stack.pop());
}
//定义字符优先级
private static int per(String value) {
if (value.equals("+") || value.equals("-")) {
return 1;
} else if (value.equals("*") || value.equals("/")) {
return 2;
} else {
throw new RuntimeException("无法识别运算符");
}
}
}
三、结果实现
总结
本次我们实现了中缀表达式转为后缀表达式以及带小括号的运算。细心的小伙伴们有没有发现,真正的计算器是可以进行小数的运算的,那么,下一篇我们就还原一个真正的计算器。