思路分析:
- 初始化两个栈,运算符栈 s1 和存储中间结果的栈 s2
- 从左到右扫描中缀表达式
- 遇到操作数,将其压入 s2
- 遇到运算符时,比较其与 s1 栈顶运算符的优先级:
(1)如果 s1 为空,或栈顶运算符为左括号 “(”,则直接将此运算符入栈
(2)否则,若优先级比栈顶运算符高,也将运算符压入栈 s1
(3) 否则,将 s1 栈顶的运算符弹出并压入栈 s2 中,再次转到 (4.1)与 s1 中新的栈顶运算符相比较
5. 遇到括号时:
(1)如果是左括号“(”,则直接压入 s1
(2) 如果是右括号“)”,则依次弹出 s1 栈顶的运算符,并压入s2,直到遇到左括号“(”为止,此时将这一对括号丢弃
6. 重复步骤2至5,直到表达式的最右边
7. 将 s1 中剩余的运算符依次弹出并压入 s2
8. 依次弹出 s2 中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
中缀表达式转后缀表达式的计算器整体代码:
/*
* 项目名称:ANA
* 文件名称:PolandNotation.java
* Date:2023/9/26 下午2:40
* Author:yan_Bingo
*/
package Learning;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @author Yan_Bingo
* @version 1.0
* Create by 2023/9/26 14:40
*/
public class PolandNotation {
public static void main(String[] args) {
// 完成一个将中缀表达式转为后缀表达式的功能
String expressin = "(3+4)*2+2/2-2";
// 中缀表达式 List
List<String> list = toInfixExpression(expressin);
System.out.println(list);
List<String> suffixExpressionList = parseSuffixExpressionList(list);
System.out.println(suffixExpressionList);
int result = calculate(suffixExpressionList);
System.out.printf("expression运算的结果是: %d", result);
}
// 将中缀表达式转化为后缀表达式
public static List<String> parseSuffixExpressionList(List<String> ls){
Stack<String> s1 = new Stack<String>(); // 符号栈
List<String> s2 = new ArrayList<String>(); // 用 List 代替数字栈,便于使用
for(String item : ls){
if(item.matches("\\d+")){ // 遇到数字,将其压入 s2
s2.add(item);
}else if(item.equals("(")){ // 遇到左括号,将其压入 s1
s1.push(item);
}else if(item.equals(")")){ // 遇到右括号,依次 s1 栈顶的运算符,并压入 s2,直到遇到左括号为止,此时将这一对括号丢弃
while(!s1.peek().equals("(")){
s2.add(s1.pop());
}
// 清除( 左括号
s1.pop();
}else{
while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
s2.add(s1.pop());
}
s1.push(item);
}
}
while (s1.size() != 0){
s2.add(s1.pop());
}
return s2;
}
// 将一个中缀表达式数字和符号依次存放在 ArrayList
public static List<String> toInfixExpression(String expression){
int index = 0;
String keep = "";
char ch = ' ';
List<String> list = new ArrayList<String>();
do{
if((ch = expression.charAt(index)) < 48 || (ch = expression.charAt(index)) > 57 ){ // 不是数字
list.add("" + ch);
index++;
}else{
// 将 keep 清空
keep = "";
while(index < expression.length() && ((ch = expression.charAt(index)) >= 48 && (ch = expression.charAt(index)) <= 57 )){
keep += ch;
index++;
}
list.add(keep);
}
}while (index < expression.length());
return list;
}
// 将一个逆波兰表达式的数字和符号依次存放在 ArrayList
public static List<String> getStringList(String suffixExpression){
// 获得一个 String 数组,用空格隔开
String [] split = suffixExpression.split(" ");
List<String> list = new ArrayList<String>();
for(String item: split){
list.add(item);
}
return list;
}
// 获得计算的结果
public static int calculate(List<String> list){
// 初始化一个栈
Stack<String> stack = new Stack<String>();
int num1 = 0;
int num2 = 0;
int result = 0;
for(String item: list){
if(item.matches("\\d+")){ //匹配的是多位数
// 直接入栈
stack.add(item);
}else{
num2 = Integer.parseInt(stack.pop());
num1 = Integer.parseInt(stack.pop());
if(item.equals("+")){
result = num1 + num2;
}else if(item.equals("-")){
result = num1 - num2;
}else if(item.equals("*")){
result = num1 * num2;
}else if(item.equals("/")){
result = num1 / num2;
}else{
throw new RuntimeException("输入的运算符有误");
}
// 再将此次计算的结果入栈
stack.add("" + result);
}
}
return Integer.parseInt(stack.pop());
}
}
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 oper){
int result = 0;
switch (oper){
case "+":
result = ADD;
break;
case "-":
result = SUB;
break;
case "*":
result = MUL;
break;
case "/":
result = DIV;
break;
default:
System.out.println("输入的运算符有误~~");
break;
}
return result;
}
}