栈实现综合计算器(中缀表达式)
❤️
来自专栏《LeetCode基础算法题》 欢迎订阅❤️
1、题目
使用栈来实现综合计算器
2、思路
看到计算器我们首先想到的数据结构是栈,为什么这么说呢?最经典的括号匹配想必大家都知道了。
-
通过一个 index 指针辅助我们遍历字符串中的数据
-
如果扫描发现是一个数字,就直接入数字栈
-
如果扫描发现是一个符号, 就分如下两种情况考虑
如果发现当前的符号栈为空,就直接入栈
如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符, 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈, 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈
4.当表达式扫描完成后,顺序的从数字栈和符号栈中pop出相应的数和符号进行运算求解,将求解的的最后结果放入数字栈中,再次弹出即可。
废话少说~~~~~上代码!
3、代码
package com.cz.Stack;
/**
* @ProjectName: Data_structure
* @Package: com.cz.Stack
* @ClassName: Cal
* @Author: 张晟睿
* @Date: 2022/3/1 15:38
* @Version: 1.0
*/
public class Cal {
public static void main(String[] args) {
//String str1 = "3+2*6-2";
String str = "700*2*2-5+1-5+3-4";
//定义两个栈
//数栈
ArrayStack2 numstack = new ArrayStack2(10);
//操作符栈
ArrayStack2 opeastack = new ArrayStack2(10);
char ch; //将每次扫描得到 char 保存到 ch
int index = 0;//指针用来扫描字符串
int oper = 0;
int num1 = 0;
int num2 = 0;
int result = 0;//用于记录存储结果
String keepNum = ""; //用于拼接 多位
while(true){
ch = str.substring(index, index + 1).charAt(0);
if (opeastack.isOpea(ch)){//判断是否为操作符
if (!opeastack.isEmpty()){//判断操作符栈是否为空
//操作符字符串不为空 与栈内的操作符进行比较 看谁的优先级比较高
if (opeastack.priority(ch) <= opeastack.priority(opeastack.peek())){
num1 = numstack.pop();
num2 = numstack.pop();
oper = opeastack.pop();
result = numstack.calculate(num1, num2, oper);
//将计算的结果继续入栈
numstack.push(result);
opeastack.push(ch);
}else{
//如果优先级比当前符号栈中的优先级大的话直接入栈
opeastack.push(ch);
}
}else{
opeastack.push(ch);
}
}else{ //如果这里是数的话 继续直接入栈
//这里要判断一下多位数的问题
//这里为啥要减去48 原因在于ch 这里存放的是字符的‘1’->49 对应的Ascll码为49
// numstack.push(ch - 48);
keepNum+=ch;
//考虑如果是最后一个数字就不用在进行判断其有几位数字
if (index == str.length() -1 ){
numstack.push(Integer.parseInt(keepNum));
}else{
if (opeastack.isOpea(str.substring(index + 1, index + 2).charAt(0))){
numstack.push(Integer.parseInt(keepNum));
keepNum = "";//这里切记用完之后一定要清除 不然会上一次的加在一起
}
}
}
index++;
if(index >= str.length()){//已经到了末尾
break;
}
}
//开始进行计算
while(true){
//如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】
if(opeastack.isEmpty()) {
break;
}
num1 = numstack.pop();
num2 = numstack.pop();
oper = opeastack.pop();
result = numstack.calculate(num1, num2, oper);
numstack.push(result);
}
//将数栈的最后数,pop 出,就是结果
int res2 = numstack.pop();
System.out.printf("表达式 %s = %d", str, res2);
}
}
class ArrayStack2{
private int maxSize;
private int[] stack;
private int top = -1;
public ArrayStack2(int maxSize){
this.maxSize = maxSize;
this.stack = new int [this.maxSize - 1];
}
public boolean isFull(){
return top == maxSize -1;
}
public boolean isEmpty(){
return top == -1;
}
//判断下一个字符是否为操作符
public boolean isOpea(char ch){
return ch=='+' || ch=='-' || ch=='*' || ch=='/';
}
//判断字符的优先级
public int priority(int ch){
if (ch=='*' || ch=='/')
return 1;
else if(ch=='+' || ch=='-'){
return 0;
}else{
return -1; // 假定目前的表达式只有 +, - , * , /
}
}
public void push(int num){
if (isFull()){
System.out.println("栈已满~~~");
}
stack[++top] = num;
}
public int calculate(int num1, int num2, int opea){
int result = 0; // res 用于存放计算的结果
switch (opea) {
case '+':
result = num1 + num2;
break;
case '-':
result = num2 - num1;//注意顺序
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num2 / num1;
break;
default:
break;
}
return result;
}
public int pop(){
if (isEmpty()){
throw new RuntimeException("栈为空~~~");
}
return stack[top--];
}
//查看栈顶元素 不删除该元素
public int peek(){
return stack[top];
}
public void list(){
if (isEmpty()){
throw new RuntimeException("栈为空~~~");
}
for (int i = top; i >= 0 ; i--) {
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
}
4、总结
该题目的最大难度在于如果出现的数字为多位数字的时候该如何解决,主要解决的对代码的逻辑思维的判断。