import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotion {
public static void main(String[] args) {
//完成将中缀表达式转化成后缀表达式
//1+((2+3)*4)-5 ==>转成 1 2 3 + 4 * 5 -
//2. 直接对str操作不方便,先将1+((2+3)*4)-5 中缀表达式对应的List
//1+((2+3)*4)-5 = > ArrayList [1,+,(,(,2,+,3,),*,4,),-,5 ]
//3.将得到的中缀表达式对应的list转成后缀表达式
//即ArrayList[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]=>ArrayList[1,2,3,+,4,*,5,-]
//定义一个逆波兰表达式
//(3+4)X5-6 ==>3 4 + 5 X 6 -
// 4 * 5 - 8 +60 + 8 /2 =>4 5 * 8 - 60 + 8 2 / +
// String suffixExpression = “4 5 * 8 - 60 + 8 2 / +”;
//思路
//1.先将“3 4 + 5 x 6 -”放入一个ArrayList中
//2.将ArrayList 传递给一个方法,遍历arrayList,配合栈完成计算
// List list = getListString(suffixExpression);
// System.out.println(“后缀表达式:”+list);
// int res = calucate(list);
// System.out.println(“运算结果为:”+res);
String expression = "1+((2+3)*4)-5";
List<String> infixExpressionList = toInfixExpressionList(expression);
System.out.println("中缀表达式:"+infixExpressionList);
List<String> SuffixExpressionList = parseSuffixExpressionList(infixExpressionList);
System.out.println("后缀表达式对应的list:"+SuffixExpressionList);
System.out.println("1+((2+3)*4)-5="+calucate(SuffixExpressionList));
}
//即ArrayList[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]=>ArrayList[1,2,3,+,4,*,5,-]
//方法:将得到的中缀表达式对应的list转成后缀表达式
private static List<String> parseSuffixExpressionList(List<String> ls){
//定义两个栈
Stack<String> s1 = new Stack<String>();//符号栈
//说明:因为s2转化过程中没有pop操作,而且后面需要逆序输出
//这里直接用List<String>代替
List<String> s2 = new ArrayList<String>();//存储中间结果的栈
//遍历ls
for(String item:ls) {
//如果是一个数,加入s2
if(item.matches("\\d+")) {
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 {
//当item的优先级小于或者等于s1栈顶优先级,
//将s1栈顶运算符弹出并加入s2中,循环比较
//写一个比较优先级高低的方法
while(s1.size()!=0&& Operation.getValue(s1.peek())>=Operation.getValue(item)) {
s2.add(s1.pop());
}
//还需要将item压入栈中
//item优先级高于s1栈顶优先级时:
s1.push(item);
}
}
//将s1中剩余运算符依次弹出加入s2
while(s1.size()!=0) {
s2.add(s1.pop());
}
return s2;//因为是存放到list中,因此按顺序输出就是对应的后缀表达式
}
//方法:将中缀表达式转成对应list
//s="1+((2+3)*4)-5";
private static List<String> toInfixExpressionList(String s){
//定义一个List存放中缀表达式对应的内容
List<String> ls = new ArrayList<String>();
int index = 0;//指针用于遍历中缀表达式字符串
String str;//用来做对多位数拼接
char c;//每遍历一个字符放入c
do {
//如果c是一个非数字,就需要加入到ls
if((c=s.charAt(index))<48 ||(c=s.charAt(index))>57) {
ls.add(""+c);
index++;//指针后移
}else {//如果是数字需要考虑多位数
str = "";//先将str置空,'0'[48]->'9'[57]
while(index < s.length() &&((c=s.charAt(index))>=48)&&(c=s.charAt(index))<=57) {
str+=c;//拼接
index++;
}
ls.add(str);
}
}while(index < s.length());
return ls;
}
//用来将中间含有空格的表达式分割为对应的list
private static List<String> getListString(String suffixExpression){
//分割suffixExpression
String[] split = suffixExpression.split(" ");
List<String> list = new ArrayList<String>();
for(String str:split) {
list.add(str);
}
return list;
}
//完成对逆波兰表达式的运算
/**
* 1.从左至右扫描,将3 4压入栈
* 2.遇到+运算符,弹出4 3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈
* 3.将5入栈
* 4.遇到x运算符,弹出 5 7,计算5x7=35,将35入栈
* 5.6入栈
* 6.遇到-运算符,计算出35-6得值,29,得出结果
*
*/
private static int calucate(List<String> ls) {
//只需要一个栈
Stack<String> stack = new Stack<String>();
//遍历ls
for(String item:ls) {
//使用中缀表达式取出数字
if(item.matches("\\d+")) {//匹配多位数
//入栈
stack.push(item);
}else {
//pop两个数字,运算,入栈
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int res = cal(num1,num2,item);
stack.push(res+"");
}
}
//最后留在栈里面的就是运算结果
return Integer.parseInt(stack.pop());
}
//四则运算方法
public static int cal(int num1,int num2,String oper) {
int res = 0;//用于存放运算结果
switch(oper) {
case"+":
res = num1+num2;
break;
case "-":
res = num2-num1;
break;
case"/":
res = num2 / num1;
break;
case "*":
res = num1*num2;
break;
default:
throw new RuntimeException("运算符有误");
}
return res;
}
}
//编写一个Operation 苦于返回一个运算符对应优先级
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 res = 0;
switch(operation) {
case"+":
res = ADD;
break;
case"-":
res = SUB;
break;
case"*":
res = MUL;
break;
case"/":
res = DIV;
break;
default:
//遇到小括号时会输出
System.out.println("不存在该运算符");
break;
}
return res;
}
}