数据结构之java数组模拟栈计算字符串运算表达式的结果
本文参考至:(对其中的逻辑错误进行了改正,对数据的精度进行了处理)
问题:
给定一个字符串,例如1*2+3/4-5,计算它的值
思考:
1.栈是一种具有先进后出的特点的数据结构
2.建立两个栈,一个数栈,用于存放表达式中的运算数,一个符号栈,存放运算符
3.从表达式字符串的第一个字符开始扫描,当扫描到数时,入数栈,当扫描到运算符时,先判断该运算符与符号栈顶的运算符优先级,若小于或等于,则从数栈中取出两个数,从符号栈中取出一个符号,进行运算,若大于,则直接入符号栈
4.当数栈中只剩一个数时,该数即为表达式的计算值
package com.yuanqiao.algorithm; public class CalculatorStack { public static void main(String[] args) { String expression = "1*2+3*4/24-6+15"; NumberStack numstack = new NumberStack(20); ComputeSignStack operstack = new ComputeSignStack(20); char ch = ' '; //存放当前扫描到的值 int index = 0; //用于遍历扫描栈 double num1 = 0; double num2 = 0; int opera = 0; double res = 0; String joint = ""; //用于拼接多位数 while(true){ //依次获取表达式字符串的每一个字符 ch = expression.substring(index,index+1).charAt(0); //将获取到的字符串转成一个字符 //判断ch类型 if(operstack.isOpera(ch)){ //判断符号栈是否为空 if(!operstack.isEmpty()){ //若符号栈不为空则判断当前符号与栈顶元素符号优先级 if(operstack.priority(ch) <= operstack.priority(operstack.gettop())){ num1 = numstack.pop(); num2 = numstack.pop(); opera = operstack.pop(); res = numstack.cal(num2,num1,opera); //计算当前运算结果 //将运算结果入数栈,当前运算符入符号栈 numstack.add(res); operstack.add(ch); } else{ operstack.add(ch); //直接将当前符号入符号栈 } }else{ operstack.add(ch); //符号栈为空则直接将当前符号入符号栈 } }else{//若当前扫描值为数,直接入数栈 //判断是否为多位数,当扫描到一个数时,不立即入栈,继续向后扫描,当扫描到符号时才入栈 joint = joint+ch; if(index == expression.length()-1){ //若当前已扫描到字符串的最后一位,则直接入栈 numstack.add(Double.parseDouble(joint)); //将字符串转换成整型数据入栈 }else{ //判断下一位是否为符号 if(operstack.isOpera(expression.substring(index+1,index+2).charAt(0))){ numstack.add(Double.parseDouble(joint)); //将字符串转换成整型数据入栈 joint = ""; //初始化joint } } } index++; if(index >= expression.length()){ break; } } //表达式字符串扫描完毕,循环取出栈中元素进行运算 while (true){ if(operstack.isEmpty()){ //若符号栈为空,则数栈中只有一个值,即为运算结果 break; } num1 = numstack.pop(); num2 = numstack.pop(); opera = operstack.pop(); res = numstack.cal(num2,num1,opera); //栈是先进后出 numstack.add(res); } double finres = numstack.pop(); //将数栈中最后一个元素取出,即为运算结果 System.out.println(expression +"="+ finres); } } //建立数字栈信息类 class NumberStack{ private int maxsize; //定义栈数组最大容量 private double[] stack; //定义栈数组 private int top = -1; //定义栈顶元素指针 //栈构造器 public NumberStack(int maxsize){ this.maxsize = maxsize; stack = new double[maxsize]; } //获取当前栈顶元素 public double gettop(){ return stack[top]; } //判断是否栈空 public boolean isEmpty(){ return top == -1; } //判断是否栈满 public boolean isFull(){ return top == maxsize - 1; } //元素入栈 public void add(double value){ //判断是否栈满 if(isFull()){ System.out.println("栈满,无法入栈"); return; } top++; stack[top] = value; } //元素出栈 public double pop(){ //判断是否栈空 if(isEmpty()){ throw new RuntimeException("栈空"); } double value = stack[top]; top--; return value; //返回出栈元素值 } //遍历打印栈所有元素 public void list(){ if(isEmpty()){ System.out.println("栈空,没有数据"); return; } //从栈顶开始遍历打印 for(int i = top;i<=0;i--){ System.out.println(stack[top]+" "); } } //计算方法 public double cal(double num1,double num2,int opera){ double res = 0; //存放计算结果 switch (opera){ case '+': res = num1 + num2; break; case '-': res=num1-num2; break; case '*': res = num1 * num2; break; case '/': res=num1/num2; break; default: break; } return res; } } //建立符号栈信息类 class ComputeSignStack{ private int maxsize; //定义栈数组最大容量 private int[] stack; //定义栈数组 private int top = -1; //定义栈顶元素指针 //栈构造器 public ComputeSignStack(int maxsize){ this.maxsize = maxsize; stack = new int[maxsize]; } //获取当前栈顶元素 public int gettop(){ return stack[top]; } //判断是否栈空 public boolean isEmpty(){ return top == -1; } //判断是否栈满 public boolean isFull(){ return top == maxsize - 1; } //元素入栈 public void add(int value){ //判断是否栈满 if(isFull()){ System.out.println("栈满,无法入栈"); return; } top++; stack[top] = value; } //元素出栈 public int pop(){ //判断是否栈空 if(isEmpty()){ throw new RuntimeException("栈空"); } int value = stack[top]; top--; return value; //返回出栈元素值 } //遍历打印栈所有元素 public void list(){ if(isEmpty()){ System.out.println("栈空,没有数据"); return; } //从栈顶开始遍历打印 for(int i = top;i<=0;i--){ System.out.println(stack[top]+" "); } } //返回运算符优先级 public double priority(double operator){ if(operator =='*' || operator == '/') return 1; if(operator =='+' || operator == '-') return 0; else return -1; } //判断是否为运算符 public boolean isOpera(int val){ return val == '+' || val == '-' || val == '*' || val == '/'; } }