输入一个字符串类型的表达式,例如:7*2*2-5+1-5+3-3,计算出结果。
1. 思路分析
①通过一个index值(索引),来遍历表达式;
②如果发现是一个数字,就直接入数栈;
③如果发现扫描到是一个符号,就分如下情况;
④如果发现当前的符号栈为空,就直接入栈
⑤如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈;
⑥如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈;
⑦当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运算;
⑧最后在数栈中只有一个数字,就是表达式的结果。
2. 代码实现
在我上一篇文章中,写了数组模拟实现栈类ArrayStack,在这个类的其他方法的基础上,再加入以下方法:
//返回运算符的优先级,数字越大,优先级越高
public int priority(int op) {
//目前只计算+、-、*、/
if (op == '*' || op == '/') {
return 1;
} else if (op == '+' || op == '-') {
return 0;
} else {
return -1;
}
}
//判断是不是运算符
public boolean isOp(char val) {
return val == '+' || val == '-' || val == '*' || val == '/';
}
//计算方法
public int cal(int num1, int num2, int op) {
int res = 0; //计算结果
switch (op) {
case '+':
res = num1 + num2;
break;
case '-':
//用后面的减前面的
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
//用后面的除前面的
res = num2 / num1;
break;
}
return res;
}
//返回当前栈顶的值,但没有出栈
public int peek() {
return stack[top];
}
在main方法中的其它逻辑:
public static void main(String[] args) {
String expression = "300+7-4-30";
//创建两个栈:一个数栈,一个符号栈
ArrayStack2 numStack = new ArrayStack2(10);
ArrayStack2 opStack = new ArrayStack2(10);
int index = 0;//指针
int num1 = 0;//取出的第一个数
int num2 = 0;//取出的第二个数
int op = 0;//取出的当前符号
int res = 0;//运算出的结果
char ch = ' ';//保存每次扫描算式得到的结果
String keepNum = "";//用于拼接多位数
//遍历expression
while (true) {
//使用substring方法得到当前位置的字符,并使用charAt方法把字符串类型转为字符型
ch = expression.substring(index, index + 1).charAt(0);
//判断ch是什么
//如果是运算符
if (opStack.isOp(ch)) {
//判断当前的符号栈是否为空
if (!opStack.isEmpty()) {
//如果符号栈有符号,将当前符号与栈顶的符号进行比较
if (opStack.priority(ch) <= opStack.priority(opStack.peek())) {
//取出前数栈的后两个数,和符号栈最后面的一个符号
num1 = numStack.pop();
num2 = numStack.pop();
op = opStack.pop();
//进行运算
res = numStack.cal(num1, num2, op);
//把运算结果加入数栈
numStack.push(res);
//把当前的符号入符号栈
opStack.push(ch);
} else {
//优先级大于栈顶的符号,直接入栈
opStack.push(ch);
}
} else {
//符号栈为空,直接加入符号栈
opStack.push(ch);
}
} else {
//处理多位数字时,需要判断下一个字符是不是数字
keepNum += ch;
//如果当前的字符是expression的最后一位,则直接入栈
if (index == expression.length() - 1) {
//将当前的keepNum转换为int类型加入数栈
numStack.push(Integer.parseInt(keepNum));
} else {
//判断当前位置的后一位是不是数字
if (opStack.isOp(expression.substring(index + 1, index + 2).charAt(0))) {//如果是运算符
//将当前的keepNum转换为int类型加入数栈
numStack.push(Integer.parseInt(keepNum));
//清空keepNum
keepNum = "";
}
}
}
index++;//指针递增
if (index >= expression.length()) {
break;
}
}
//按顺序从数栈和符号栈取出数和符号进行运算
while (true) {
//如果符号栈为空,则得到最后的结果
if (opStack.isEmpty()) {
break;
}
//取出前数栈的后两个数,和符号栈最后面的一个符号
num1 = numStack.pop();
num2 = numStack.pop();
op = opStack.pop();
//进行运算
res = numStack.cal(num1, num2, op);
//把运算结果加入数栈
numStack.push(res);
}
System.out.println("表达式 " + expression + " 结果为 " + numStack.pop());
}