使用栈实现简单计算器
思路
- 通过一个index值(索引) ,来遍历我们的表达式,如 “100+2*6-2”
- 如果我们发现是一个个数字,就直接入数栈
- 如果发现扫描到是一个符号,就分如下情况:
3.1 如果发现当前的符号栈为空,就直接入栈
3.2 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果入数栈,然后将当前的操作符入符号栈,如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈. - 当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并将计算结果放入数栈
- 最后在数栈只有一个数字,就是表达式的结果
代码实现
只需要根据思路一步一步的写就可以实现,可以参考注释理解
计算机类
public class Calculator {
public static void main(String[] args) {
//操作符栈
ArrayStack operatorStack = new ArrayStack(10);
//操作数栈
ArrayStack numStack = new ArrayStack(10);
String expression = "100+2*6-2";
calculate(expression, operatorStack, numStack);
}
public static void calculate(String s, ArrayStack operatorStack, ArrayStack numStack) {
//入栈操作
int index = 0;
String keepNum = "";
while (true) {
char c = s.charAt(index);
//如果我们发现是一个个数字,就直接入数栈(注意将char型转换为int型)
if (c >= 48 && c <= 57) {
// int num = c - 48;
// numStack.push(num);
//TODO 如何处理多位数的问题 如 70+2*6-2
//分析思路
//1.当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
//2.在处理数,需要向express ion的表达式的index后再看一位,如果是数就进行扫描,如果是符号才入栈
//3.因此我们需要定义一个变量字符串,用于拼接处理多位数
keepNum += c;
//如果c已经是expression的最后一位,就直接入栈
if (index + 1 == s.length()) {
numStack.push(Integer.parseInt(keepNum));
} else {
//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
//注意 是看后一位,不是index++
char c1 = s.charAt(index + 1);
if (c1 == 42 || c1 == 43 || c1 == 45 || c1 == 47) {//如果是运算符,
//则将拼接好的该数入栈
numStack.push(Integer.parseInt(keepNum));
//注意,要清空keepNum,避免下次出现多位数时收到之前数据的影响
keepNum = "";
}
}
}
//如果发现扫描到是一个符号 (注意将char型转换为int型)
if (c == 42 || c == 43 || c == 45 || c == 47) {
if (operatorStack.isEmpty()) {
int operator = c;
operatorStack.push(operator);
} else {
Integer top = operatorStack.getTop();
int i = top.intValue();
//如果当前的操作符的优先级小于或者等于栈中的操作符
if (priority(c) <= priority((char) i)) {
Integer popNum1 = numStack.pop();
Integer popNum2 = numStack.pop();
Integer popOperator = operatorStack.pop();
int i1 = popOperator.intValue();
int cal = cal(popNum1, popNum2, (char) i1);
numStack.push(cal);
operatorStack.push((int) c);
}
//如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈.
if (priority(c) > priority((char) i)) {
operatorStack.push((int) c);
}
}
}
index++;
if (index >= s.length()) {
break;
}
}
//计算操作 当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行.最后在数栈只有一个数字(运算符栈为空),就是表达式的结果
//运算栈为空则说明计算完成
while (!operatorStack.isEmpty()) {
Integer popNum1 = numStack.pop();
Integer popNum2 = numStack.pop();
Integer popOperator = operatorStack.pop();
int i1 = popOperator.intValue();
int cal = cal(popNum1, popNum2, (char) i1);
numStack.push(cal);
}
Integer top = numStack.getTop();
System.out.println(top);
}
//为运算符分配优先级
public static int priority(char c) {
if (c == '*' || c == '/') {
return 1;
}
if (c == '-' || c == '+') {
return 0;
}
return -1;//传入的符号不是运算符
}
//计算方法
public static int cal(int num1, int num2, char operator) {
int result = 0;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num2 - num1;//减(除)是后出栈的为被减数(被除数)
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num2 / num1;//减(除)是后出栈的为被减数(被除数)
break;
default:
System.out.println("无法识别运算符" + operator);
result = -1;
break;
}
return result;
}
}
栈类
class ArrayStack {
private int maxsize;
private int[] stack;
private int top;
public ArrayStack() {
}
//初始化栈
public ArrayStack(int maxsize) {
this.maxsize = maxsize;
this.stack = new int[maxsize];
top = -1;
}
//判断是否为空
public boolean isEmpty() {
if (this.top == -1) {
return true;
}
return false;
}
//判断是否为满
public boolean isFull() {
if (this.top == maxsize - 1) {
return true;
}
return false;
}
//压栈
public void push(Integer num) {
if (isFull()) {
System.out.println("栈已满");
return;
}
top++;
stack[top] = num;
}
//出栈
public Integer pop() {
if (isEmpty()) {
System.out.println("栈为空");
throw new RuntimeException("栈为空,无法弹栈");
}
Integer num = stack[top];
top--;
return num;
}
//获取栈顶元素,但不弹出
public Integer getTop(){
if(top == -1){
System.out.println("栈为空");
throw new RuntimeException("栈为空");
}
return stack[top];
}
//遍历栈
public void print() {
int n = top;
while (n != -1) {
System.out.println(stack[n]);
n--;
}
}
}
当然也可以不使用自定义的栈类