蓝桥杯 算法训练 表达式计算 java
题目
问题描述
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。
输入输出样例
输入格式
输入一行,包含一个表达式。
输出格式
输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
表达式长度不超过100,表达式运算合法且运算过程都在int内进行。
思路
在学习数据结构的时候,有学习过相关的方法,记得使用堆栈实现。在查找教材之后发现,教材上使用的是先将中缀表达式转化为后缀然后使用单个堆栈完成表达式的计算。
我在网上发现一个个人觉得更好的方法,使用两个堆栈,一个用来存放数字,另一个用来存放符号。用空间换取时间,同时也降低了算法的难度。
着道题的难点在于处理优先符号运算的问题,乘除法,括号内优先运算这两个规则的处理。
在向符号栈存入符号之前先进行符号比较,具体的比较规则封装在函数中,若栈顶符号op1优先级大于登入正入栈符号op2,则pop栈顶符号和数字栈进行运算。再将op2入栈。
在遍历过程结束后可能符号栈和数字栈还存在未遍历结束的情况,这个时候做循环直到数字栈留下一个数字。
代码
package standrad;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
/**
* 算法训练 表达式计算
* Created by Administrator on 2018/1/30.
*/
public class Main19 {
//方法一
//先将中缀转换为后缀,用后缀计算表达式值
//使用Arraylist代替栈
//方法二
//创建两个堆栈,放符号栈和数字栈
//分别抽取进行运算
static Stack<Integer> integers=new Stack<>();
static Stack<Character> characters=new Stack<>();
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String str=in.nextLine();
characters.push('#');
char[] chs=str.toCharArray();
int num=0;
//数字
for(int i=0;i<str.length();i++){
if(chs[i]>='0'&&chs[i]<='9'){
num=chs[i]-'0';
for (i = i + 1; i < str.length(); i++) {
if ('0' <= chs[i] && chs[i] <= '9') {
num = num * 10 + (chs[i] - '0');
} else {
i--;
break;
}
}
integers.push(num);
continue;
}
//运算符
if(chs[i]=='+'||chs[i]=='-'||chs[i]=='*'||chs[i]=='/'){
while (opCompare(characters.peek(),chs[i])&&integers.size()>1){
calc();
}
characters.push(chs[i]);
continue;
}
if(chs[i]=='('){
characters.push(chs[i]);
continue;
}
if(chs[i]==')'){
while (characters.peek()!='('&&integers.size()>1){
calc();
}
characters.pop();
}
}
while (integers.size()>1){
calc();
}
System.out.println(integers.get(0));
}
/**
*
* @param op1 栈顶符号
* @param op2 入栈符号
* @return
*/
public static boolean opCompare(char op1,char op2){
if(op1=='*'||op1=='/'){
return true;
}
if(op2=='*'||op2=='/'||op1=='('){
return false;
}
return true;
}
public static void calc(){
char op=characters.pop();
int num2=integers.pop();
int num1=integers.pop();
switch (op){
case '+':
integers.push(num1+num2);
break;
case '-':
integers.push(num1-num2);
break;
case '*':
integers.push(num1*num2);
break;
case '/':
integers.push(num1/num2);
break;
default:break;
}
}
}