栈实现简易计算器
之前的博客已经介绍了栈数据结构,栈有着数据先进后出的特点,因此用于实现简易计算器时相当方便。本博文中将介绍如何用栈实现一个可以进行简单四则运算不含括号的简易计算器(中缀表达式)
思路
- 首先创建两个栈,一个用于存储数而另一个用于存储运算符号。
- 首先需要一个index索引来遍历表达式
- 遍历到数字时直接入数栈
- 遍历到运算符时需要分情况讨论
- 如果当前符号栈为空直接入栈
- 如果当前符号栈不为空需要分情况讨论
- 当前遍历到的运算符的运算优先级小于或者等于栈中的运算符优先级,先从数栈中取出两个数和从字符栈中取出一个运算符,将其进行运算之后将得到的新的数存入数栈,最后将当前遍历到的运算符存入字符栈
- 当前遍历到的运算符的运算优先级大于栈中的运算符优先级则直接存入字符栈
- 当表达式遍历完之后,从数栈和符号栈依次取出相应的数和符号并计算
- 当数栈只剩下一个数字时,计算完毕,此时该数为最终结果。
代码实现
栈结构
用之前的方法用数组模拟栈
class CalculatorStack
{
private int maxSize;
private int[] stack;
private int top = -1;
public CalculatorStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
/**
*
* @return 返回栈顶的数据<不弹出数据>
*/
public int peek()
{
return stack[top];
}
public boolean isFull()
{
return top == maxSize - 1;
}
public boolean isEmpty()
{
return top == -1;
}
public void push(int value)
{
if (isFull())
{
throw new RuntimeException("栈满无法添加数据....");
}
top++;
stack[top] = value;
}
public int pop()
{
if (isEmpty())
{
throw new RuntimeException("栈空无法返回数据....");
}
return stack[top--];
}
}
运算方法
/**
* 返回运算符的优先级
* @param operation
* @return 返回数字代表优先级 数字越大优先级越高
*/
public int getPriority(int operation)
{
if (operation == '*' || operation == '/')
{
return 1;
}
else if (operation == '+' || operation == '-')
{
return 0;
}else
{
throw new RuntimeException("输入操作符有误!");
}
}
/**
* 判断是否是运算符
* @param val
* @return
*/
public boolean isOperation(int val)
{
return val == '+' || val == '-' || val == '*' || val == '/';
}
private int calculate(int num1,int num2,int operation)
{
int result = 0;
switch (operation)
{
case '+':
result = num2 + num1;
break;
case '-':
//注意顺序
result = num2 - num1;
break;
case '*':
result = num2 * num1;
break;
case '/':
//注意顺序
result = num2 / num1;
break;
}
return result;
}
核心方法
public static void calculate(String expression)
{
//创建两个栈 一个数栈 一个符号栈
CalculatorStack numStack = new CalculatorStack(2002);
CalculatorStack operationStack = new CalculatorStack(519);
//定义相关变量
int index = 0;
int num1,num2,result;
int operation;
//用于拼接多位数
String keepNum = "";
while (true)
{
//依次得到expression中的每一个字符
char ch = expression.substring(index, index + 1).charAt(0);
//如果是运算符
if (operationStack.isOperation(ch))
{
//判断符号栈是否为空
if (!operationStack.isEmpty())
{
//如果当前操作符优先级大于栈中的所有操作符,直接入栈
if (operationStack.getPriority(ch) > operationStack.getPriority(operationStack.peek()))
{
operationStack.push(ch);
}
//如果当前操作符的优先级小于或等于栈中的操作符,先弹出符号栈栈顶的操作符和数栈的头两个数据
else
{
num1 = numStack.pop();
num2 = numStack.pop();
operation = operationStack.pop();
result = numStack.calculate(num1,num2,operation);
//运算结果入数栈
numStack.push(result);
//符号ch入符号栈
operationStack.push(ch);
}
}else
{
//符号栈为空直接入栈
operationStack.push(ch);
}
}
//如果是数直接入数栈
else
{
//1.当处理多位数时,不可以直接入栈,可能是多位数
//2.处理多位数时需要看expression表达式index位置的后一位是什么,如果是数字需要继续读取否则直接入栈
//3.因此需要定义一个变量字符串用于拼接数字
keepNum+=ch;
//如果当前处于表达式的末尾
if (index == expression.length() - 1)
{
numStack.push(Integer.parseInt(keepNum));
keepNum = "";
}else
{
//判断下一位是否是字符
if (operationStack.isOperation(expression.substring(index+1,index+2).charAt(0)))
{
numStack.push(Integer.parseInt(keepNum));
//重置keepNum!!!!!
keepNum = "";
}
//1 != '1' ---> 1 = '1' - 48;
//numStack.push(ch - 48);
}
}
//让index+1,并且判断是否扫描到expression最后
index++;
if (index >= expression.length())
{
break;
}
}
//当表达式扫描完毕就顺序地从数栈和符号栈中取出相应的数和符号
while (true)
{
//如果符号栈为空--->计算完毕
if (operationStack.isEmpty())
{
break;
}
num1 = numStack.pop();
num2 = numStack.pop();
operation = operationStack.pop();
result = numStack.calculate(num1,num2,operation);
numStack.push(result);
}
result = numStack.pop();
System.out.printf("表达式:%s=%d",expression,result);
}
测试
public class Calculator
{
public static void main(String[] args)
{
String expression = "100+20*2-4";
CalculatorStack.calculate(expression);
}
}
//-----------------------------------------------------测试结果----------------------------------------------------
表达式:100+20*2-4=136
以上。
如有不足或错误欢迎评论指正