描述:
输入一串字符串,输出它的计算结果。//考虑输入不正确的情况
例如输入:722-5+1-5+3-4 输出18
代码如下:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
Stack<Character> stack2 = new Stack<>();
Stack<Integer> stack1 = new Stack<>();
int i=0;
int num = 0;
//扫描表达式
for(i=0;i<str.length();i++) {
if(i==str.length()-1) {
num = num*10+str.charAt(i)-'0';
stack1.push(num);
}
if((str.charAt(i)>='0')&&(str.charAt(i)<='9')) {
num = num*10+str.charAt(i)-'0';
}
else {
stack1.push(num);
num = 0;
if(stack2.isEmpty()) {
stack2.push(str.charAt(i));
} else if(str.charAt(i)=='+' || str.charAt(i)=='-') {
int n2 = stack1.pop();
int n1 = stack1.pop();
char ch1 = stack2.pop();
if(ch1=='+') {
stack1.push(n1+n2);
stack2.push(str.charAt(i));
} else if(ch1=='-') {
stack1.push(n1-n2);
stack2.push(str.charAt(i));
}
else if(ch1=='*') {
stack1.push(n1*n2);
stack2.push(str.charAt(i));
}
else if(ch1=='/') {
stack1.push(n1/n2);
stack2.push(str.charAt(i));
}
} else if(str.charAt(i)=='*' || str.charAt(i)=='/') {
char ch1 = stack2.pop();
if(ch1=='*' || ch1=='/') {//优先级相同
int n1 = stack1.pop();
int n2 = stack1.pop();
if(ch1=='*') {
stack1.push(n1*n2);
stack2.push(str.charAt(i));
}
else if(ch1=='/') {
stack1.push(n1/n2);
stack2.push(str.charAt(i));
}
}
else {//if(ch1=='*' || ch1=='/') //优先级大于
stack2.push(str.charAt(i));
}
}
}
}
//表达式扫描完毕后
while (!stack2.isEmpty()) {
int n2 = stack1.pop();
int n1 = stack1.pop();
char ch1 = stack2.pop();
if(ch1=='+') {
stack1.push(n1+n2);
}
else if(ch1=='-'){
stack1.push(n1-n2);
}
else if(ch1=='*'){
stack1.push(n1*n2);
}
else if(ch1=='/'){
stack1.push(n1/n2);
}
}
System.out.println(stack1.pop());
}
相信很多小伙伴第一次接触这种题目一般题目都给出了解题思路,我们只需要按照思路写代码就行了,例如:
从头开始扫描字符串,如果是数字,直接入数字栈,如果是符号则分情况讨论:
- 如果符号栈为空,则直接入栈
- 如果当前符号优先级小于等于符号栈顶优先级,则从数字栈取两个数字,从符号栈取一个符号,计算的结果弹入数字栈,然后把该符号入栈。
- 如果当前符号优先级大于符号栈顶符号优先级,则直接入栈。
当字符串扫描完毕后,则循环弹出计算,并将结果入数字栈。最后数字栈只剩一个数字,这就是表达式的结果。
很多人可能当时做出来了,但是对于为什么要这么做并不是很清楚,或者说难以记住这些计算步骤,如果下一次一样的题目但是没有提示的话也做不出来。
下面我就分享一下自己的心得,关于计算步骤。
主要是对于符号的观察。
1+2+3*4+5
对于上面的表达式,我们来逐一观察每个符号。首先是 + ,我们看到第一个+号的左右有两个操作数,但是此时我们不能急着计算,为什么?因为第一个操作数只属于第一个 +,无论如何他都会参与第一个 + 号的运算,但是第二个操作数可不止属于第一个+ 号,他还属于第二个符号,也就是 第二个 + ,所以我们这时候比较第一个符号和第二个符号的优先级,如果 1 > 2,说明1符号优先计算,这时候符号 1 左右的两个数都会优先参与它的计算,所以符号1就可以直接计算了,这就是为什么当前符号优先级小于等于符号栈顶优先级,则从数字栈取两个数字,从符号栈取一个符号,计算的结果弹入数字栈
这时候表达式变为
(1+2)+3*4+5
1+2的结果作为第二个+号的操作数之一,并且这个操作数只属于 + 号,但是+ 号右边的3 同时属于两个符号,所以我们接着看下一个符号 * ,乘号的优先级大于 + 号,所以3因该属于 乘号,所以+ 并不能计算,而乘号也只是拥有了一个操作数,还得继续看右边的数,只能入栈待定。这就是为什么如果当前符号优先级大于符号栈顶符号优先级,则直接入栈
你明白了吗?😉