import java.util.*;
public class Main {
// 判断是否是运算符的方法
public static boolean isOper(char target){
if(target == '+' || target == '-' || target == '*' || target == '/')
return true;
return false;
}
public static int priority(String res){
if(res.equals("*") || res.equals("/") ) return 2;
else if(res.equals("-") || res.equals("+")) return 1;
else return -1;
}
public static void main(String[] args) {
Stack<String> s1 = new Stack<>();// 运算符栈
Queue<String> s2 = new ArrayDeque<>();// 临时存放逆波兰算式的队列
Scanner sc = new Scanner(System.in);
String target1 = sc.nextLine();
StringBuffer target = new StringBuffer();
for(int i = 0; i < target1.length(); i++)
{
if(target1.charAt(i) == '[' || target1.charAt(i) == '{' ) target.append('(');
else if(target1.charAt(i) == ']' || target1.charAt(i) == '}' ) target.append(')');
else target.append(target1.charAt(i));
}
boolean flag = false;// 判断是运算符还是
for (int i = 0; i < target.length(); i++) {
if(target.charAt(i) >= '0' && target.charAt(i) <= '9')// 3.如果是数字,直接入队s2
{
StringBuffer bfTemp = new StringBuffer(); // 这个用来判断是不是二位数以上的数字
bfTemp.append(target.charAt(i));
boolean flagTemp = false;
int j = i;
j++;
if(j < target.length()) // 得先判断,不然判断到最后一个数字的时候就会报错,越界异常
while(target.charAt(j) >= '0' && target.charAt(j) <= '9' ) // 如果单纯使用上面的式子来判断当前的字符是否是数字的时候,会发生一个问题,只能AC个位数的式子
{
bfTemp.append(target.charAt(j));
j++;
flag = false;
flagTemp = true;
}
s2.offer(bfTemp.toString());// offer是添加元素的方法
if(flagTemp){// 如果不是个位数
// i需要改变
i = --j; // 记得将这里--,否则i会多了1
}
else flag = false;
}else if(isOper(target.charAt(i))){ // 4. 如果是运算符
// 如果不是负数,才能执行下面的
if(flag){
int j = i;
s2.offer(target.charAt(j)+""+target.charAt(++i));
// s1.push(target.charAt(j)+""+target.charAt(i++));
flag = false;
continue;
}
while(true){
// 4.1 如果运算符栈为空,或者栈顶是'(',直接入栈,入的是运算符栈
if(s1.isEmpty() || "(" == s1.peek()) {
s1.push(target.charAt(i) + "");
flag = true;
break;// 结束当前情况
}
else if(priority(String.valueOf(target.charAt(i))) > priority(s1.peek())) // 如果没有满足4.1,那就查看当前的运算符和栈顶的运算符的优先级
{// 4.2 查看优先级,优先级高就入栈
s1.push(target.charAt(i) + "");
flag = true;
break;// 结束当前情况
}else{
// 4.3 不满足上面情况,也就是优先级比较低,那就直接将栈顶元素放到队列中
s2.offer(s1.pop());
flag = true;
}
}
}else if('(' == target.charAt(i))// 如果不是运算符
{
// 5.1 遇到左括号,直接入栈s1
s1.push(target.charAt(i)+"");
} else if(')' == target.charAt(i))
{
// 遇到右括号
while(true ){
String top = s1.pop();
// 不断弹出s1栈中的运算符,然后加入s2,直到遇到左括号为止
if(top.equals("(")){ // 一定要用这个来比较字符串是否相等
break;
}else{
s2.offer(top);
}
}
}
// System.out.println(s1.toString() +"haha");
}
while(!s1.empty()){
// 6. 如果结束循环之后,s1的栈还没空,那就将s1的元素一次弹出并且进入s2队列
s2.offer(s1.pop());
}
// System.out.println(s2.toString());
//
List<String> ls = new ArrayList<>();
while (!s2.isEmpty()) {
ls.add(s2.poll());
}
Stack<String> stack = new Stack<>();
// 遍历队列,并且压入栈中
// 下面是计算逆波兰计算式的计算过程
for (String l : ls) {
if(l.charAt(0) >= '0' && l.charAt(0) <= '9' || l.length() >= 2){
// 如果当前字符是数字,就直接压入栈中
stack.push(l);
}else{
// 如果是运算符,次顶元素 运算符 栈顶元素
String sec = stack.pop();// 栈顶元素
String first = stack.pop();// 次顶元素
int res ;
if(l.charAt(0) == '+'){
res = Integer.valueOf(first) + Integer.valueOf(sec);
// 将结果压入栈中
stack.push(String.valueOf(res));
}else if(l.charAt(0) == '-'){
res = Integer.valueOf(first) - Integer.valueOf(sec);
// 将结果压入栈中
stack.push(String.valueOf(res));
}
else if(l.charAt(0) == '*'){
res = Integer.valueOf(first) * Integer.valueOf(sec);
// 将结果压入栈中
stack.push(String.valueOf(res));
}
else if(l.charAt(0) == '/'){
res = Integer.valueOf(first) / Integer.valueOf(sec);
// 将结果压入栈中
stack.push(String.valueOf(res));
}
}
}
System.out.println(stack.peek());
}
}
- 先计算逆波兰解析式,然后需要判断是不是负数,因为负数和运算符是交替出现的,可以使用一个flag来判断,下一个出现的运算符是不是符号。
- 生成解析式队列之后就可以通过计算步骤来进行计算了。