题目1
-
正文:
输入一个字符串类型的算术表达式子,返回一个数值,表示它的计算结果
例如:输入:“7+1021+4-5” ,输出:72。 -
思路分析:
- 首先需要遍历这个字符串,然后将每一个字符都进行判断然后分类
- 如果是一个数字改如何处理?如果是一个运算符又如何处理?
- 显然,这里的难点在于运算符是有优先级的,当前运算符能否直接运算取决于下一个运算符的优先级,所以我们得根据下一运算符的优先级来判断当前的运算符,反过来说,我们可以根据当前运算符与上一个运算符优先级的比较来确定运算顺序
- 我们以人的思维来计算这一串的运算表达式
7+10*2*1+4-5 =7+10*2+4-5 =7+20+4-5 =27+4-5 =31-5 =26
- 从上面的式子可以知道,我们将暂时不运算的式子存储在容器中,然后通过运算符优先级的判断来决定是否进行当前运算(如果是后面的运算的优先级小于当前运算符的优先级,则直接运算;否则需要存储在容器中,再往后看一个运算符)
- 显然后面一个运算符是比较对象,所以我们将比较的顺序变成当前运算符和前一个运算符之间的优先级比较,显然比较是从第二个运算符开始。
-
实现:
- 用一个数栈来存储数值,用一个符号栈来存储运算符
- 遍历字符串类型的算术表达式
- 如果是数值,直接入栈
- 如果是运算符分情况讨论:
- 如果栈中没有运算符,直接压入栈中
- 如果栈中有运算符,则比较运算符的优先级
- 如果优先级大于栈顶的运算符,则压入栈中
- 如果优先级小于或等于栈顶运算符,则从数栈中取出两个数,从运算符栈中取出一个运算符进行计算,然后将运算的结果压入数栈,最后把当前运算符压入栈中
- 遍历完成之后,如果符号栈不为空,则重复执行取出数值和运算符运算,然后将结果压入数栈的步骤,
- 最后当符号栈中的数被取完,数栈中的元素只有一个时,把它取出即为最后的结果
-
代码:
public static void main(String[] args) { // System.out.println((int)'0');//0的符号的值为48,数值和字符型的数字相差48,数值=数字-48 System.out.println(count("1*3/2+4+7+8+7")); } /** * 实现方法 * @param exp 表达式的字符串 * @return 最总的结果 */ public static Double count(String exp) { // 1.创建两个栈,一个是数栈,一个是符号栈 Stack<Double> num = new Stack<>(); Stack<Character> ope = new Stack<Character>(); char c = '0'; for(int index=0;index < exp.length();index++) { c = exp.charAt(index); if(isOperational(c)) {//判断是否是运算符 if(ope.isEmpty()||precedence(c,ope.peek())){//如果栈为空,或者优先级较高,则直接压入栈中 ope.push(c); }else {// double a = num.pop(); double b = num.pop(); char ch = ope.pop(); num.push(count(b,a,ch)); ope.push(c); } }else {//如果不是运算符,则该字符为数字,直接入栈 num.push((double) (c-48)); } } while(num.size()>=2) { Double a = num.pop(); Double b = num.pop(); char ch = ope.pop(); num.push(count(a,b,ch)); } return num.pop(); } // 判断是不是数字字符 public static boolean isOperational(char ch) { return ch<48; } // 判断字符的优先级 public static boolean precedence(char a,char b) { double ap = 0;double bp = 0; if(a=='-'||a=='+') { ap = 0; }else { ap = 1; } if(b=='-'||b=='+') { bp = 0; }else{ bp = 1; } return ap>bp; } // 运算输入的字符 public static double count(double a,double b,char c) { if(c=='+') { return a+b; } if(c=='-') { return a-b; } if(c=='*') { return a*b; } if(c=='/'&& b != 0) { return a/b; }else { System.out.println("没有找到结果"); return -9999999; } } }
-
改进:多位数的四则运算
public static void main(String[] args) {
// System.out.println((int)'0');//0的符号的值为48,数值和字符型的数字相差48,数值=数字-48
// System.out.println((int)'/');
//'+' 43
//'-' 45
//'*' 42
//'/' 47
System.out.println(count("200000/10"));//只能做个位数的加减
}
/**
* 实现方法
* @param exp 表达式的字符串
* @return 最总的结果
*/
public static Double count(String exp) {
// 1.创建两个栈,一个是数栈,一个是符号栈
Stack<Double> num = new Stack<>();
Stack<Character> ope = new Stack<Character>();
char c = '0';
String keepNum="";
for(int index=0;index < exp.length();index++) {
c = exp.charAt(index);
if(isOperational(c)) {//判断是否是运算符
if(ope.isEmpty()||precedence(c,ope.peek())){//如果栈为空,或者优先级较高,则直接压入栈中
ope.push(c);
}else {//栈部
double a = num.pop();
double b = num.pop();
char ch = ope.pop();
num.push(count(b,a,ch));
ope.push(c);
}
}else {//如果不是运算符,则该字符为数字,直接入栈
keepNum +=c;
if(index==exp.length()-1) {
num.push((double) Integer.parseInt(keepNum));
}else if(isOperational(exp.substring(index+1,index+2).charAt(0))) {
num.push((double) Integer.parseInt(keepNum));
//重要 keepNum清空
keepNum = "";
}
}
}
while(num.size()>=2) {
Double a = num.pop();
Double b = num.pop();
char ch = ope.pop();
num.push(count(b,a,ch));
}
return num.pop();
}
// 判断是不是数字字符
public static boolean isOperational(char ch) {
return ch<48;
}
// 判断字符的优先级
public static boolean precedence(char a,char b) {
double ap = 0;double bp = 0;
if(a=='-'||a=='+') {
ap = 0;
}else {
ap = 1;
}
if(b=='-'||b=='+') {
bp = 0;
}else{
bp = 1;
}
return ap>bp;
}
// 运算输入的字符
public static double count(double a,double b,char c) {
if(c=='+') {
return a+b;
}
if(c=='-') {
return a-b;
}
if(c=='*') {
return a*b;
}
if(c=='/'&& b != 0) {
return a/b;
}else {
System.out.println("没有找到结果");
return -9999999;
}
}
```