import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
/*
- 中缀转后缀:
- 1.初始化俩个栈:运算符栈s1和存储中间结果的栈s2;
- 2.从左到右扫描中缀表达式
- 3.如果遇到操作数的时候,直接压入栈s2
- 4.如果遇到操作符的时候,比较其与s1栈顶运算符的优先级:
- (1).如果s1为空或者栈顶运算为左括号“(”,则直接让此运算符入栈;
- (2)否则。若优先级比栈顶运算符高,也将运算符压入栈s1
- (3)否则,将s1栈顶运算符弹出压入到s2中,再次转入到4.1与栈顶操作符进行比较
- 5.遇到括号时:
- (1)如果遇到左括号就直接压入s1,
- (2)如果遇到右括号,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,然后将这一对
- 括号丢弃
- 6.重复步骤2至5,直到表达式的最右边
- 7,将s1中剩余运算符依次弹出并压入s2
- 8.依次弹出s2中表达式,并逆序输出的结果就为后缀表达式
*/
public class Main {
public static void main(String[] args) {
/*
* 所谓前缀。中缀,后缀是相对于操作符来说的,前缀是说操作符在前面
*/
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
InversePolishExpression ipe=new InversePolishExpression();//逆波兰表达式的计算
ArrayList infixList=ipe.InfixExpression(s);//将字符串转换成中缀表达式
System.out.println(“中缀表达式为:”+infixList);
ArrayList suffixList=ipe.infixSuffix(infixList);//将中缀表达式转换成后缀表达式
System.out.println(“后缀表达式为:”+suffixList);
int result=ipe.CalculateTheSuffix(suffixList);//计算后缀表达式
System.out.println(result);
}
}
class InversePolishExpression{//逆波兰表达式的计算
/*
* //将字符串转换成中缀表达式
/
public ArrayList InfixExpression(String s){
ArrayList infixList=new ArrayList();//用来存放中缀表达式的集合
/
* 如果直接采用这个遍历字符串的方式,将数字和操作符取出,会出现一些问题
* 例如:27+8 就会变成 2 7 + 8 在计算的过程中出现一些问题。
*
for(int i=0;i<s.length();i++) {//遍历字符串
String temp=String.valueOf(s.charAt(i));//将每一个字符转换成字符串,存入前缀集合中
infixList.add(temp);
}
*/
int i=0;//遍历字符串的索引
do {
String str="";//拼接多位数字的字符串
if(s.charAt(i)<48||s.charAt(i)>57) {//如果是操作符的话,就直接入集合
infixList.add(String.valueOf(s.charAt(i)));
i++;
}else {//如果是数字的话,就要考虑多位数的情况
while(i<s.length()&&s.charAt(i)>=48&&s.charAt(i)<=57) {
str+=s.charAt(i);
i++;
}
infixList.add(str);
str="";
}
}while(i<s.length());
return infixList;
}
/*
* //将中缀表达式转换为后缀表达式
*/
public ArrayList<String> infixSuffix(ArrayList<String> infixList){
Stack<String> s1=new Stack<String>();//用来存放操作符的栈
/*
* 这里由于栈s2没有出栈的情况,而且最后转换为后缀表达式的时候,还需要逆序输出
* 因此,为了简化过程,将中间存储情况直接add进后缀的集合中
*/
//Stack<String> s2=new Stack<String>();//用来存放中间结果的栈
ArrayList<String> suffixList=new ArrayList<String>();//用来存放后缀表达式的集合
for(String s:infixList) {//遍历前缀集合
if(s.matches("\\d+")) {//如果是数字就直接加到后缀表达式中
suffixList.add(s);
}else if(s.equals("(")){//如果是左括号也直接加到后缀表达式中
s1.push(s);
}else if(s.equals(")")) {//如果遇到有括号,就要不断的将栈中操作符弹出,直到遇到(括号结束,然后将一对括号消除
while(!s1.peek().equals("(")) {
suffixList.add(s1.pop());
}
s1.pop();
}else {//如果是操作符,就要判断该操作符与栈顶的操作符的优先级
while(s1.size()>0&&Opertion.getValue(s1.peek())>=Opertion.getValue(s)) {
suffixList.add(s1.pop());
}
s1.push(s);
}
}
while(s1.size()>0) {//遍历结束以后,将栈中剩余的操作符全部压到后缀表达式中
suffixList.add(s1.pop());
}
return suffixList;
}
/*
* 计算后缀表达式的结果
*/
public int CalculateTheSuffix(ArrayList<String> suffixList) {
Stack<String> stack=new Stack<String>();
for(String s:suffixList) {//遍历后缀表达式
if(isOpertion(s)) {//如果是操作符,就取出栈顶和次栈顶俩个数进行计算
int num1=Integer.valueOf(stack.pop());
int num2=Integer.valueOf(stack.pop());
int result=count(num1, num2, s);
stack.push(String.valueOf(result));
}else {
stack.push(s);
}
}
return Integer.valueOf(stack.pop());
}
/*
* 判断字符串是否为操作符
*/
public boolean isOpertion(String s) {
return s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/");
}
/*
* 计算值
*/
public int count(int num1,int num2,String opertion) {
switch (opertion) {
case "+":
return num1+num2;
case "-":
return num2-num1;
case "*":
return num1*num2;
case "/":
return num2/num1;
default:
throw new RuntimeException("操作符错误");
}
}
}
class Opertion{//判断操作符的优先级
private static int ADD=1;//加的优先级为1
private static int SUB=1;//减的优先级为1
private static int MUL=2;//乘的优先级为2
private static int DIV=2;//除的优先级为2
public static int getValue(String opertion) {
int result=0;
switch (opertion) {
case "+":
result=ADD;
break;
case "-":
result=SUB;
break;
case "*":
result=MUL;
break;
case "/":
result=DIV;
break;
default:
System.out.println("不存在"+opertion+"运算符");
}
return result;
}
}
结果: