在跟着韩老师学习数据结构,在栈这一章中,有个综合计算器,觉得老师的代码可以再稍微优化一下。我用到了集合,先将运算字符串做了转换,这样计算就不会被数字的位数限制了。代码如下,请多指教。
创建栈
package com.m.demo6;
import java.util.Arrays;
public class ArrayStack {
private int maxsize;
private int [] array;
private int top;
public ArrayStack(int maxsize) {
this.maxsize = maxsize;
this.array=new int[maxsize];
this.top=-1;
}
public boolean isFull() {
return top==maxsize-1;
}
public boolean isEmpty() {
return top==-1;
}
public void push(int i) {
if(isFull()) {
System.out.println("栈满");
return;
}
top++;
array[top]=i;
}
public int pop() {
if(isEmpty()) {
System.out.println("栈空");
return -1;
}
int temp=array[top];
top--;
return temp;
}
// 打印top
public int peek() {
if(isEmpty()) {
System.out.println("栈空");
// return -1;
}
// System.out.println(array[top]);
return array[top];
}
@Override
public String toString() {
return "ArrayStack [array=" + Arrays.toString(array) + "]";
}
}
实现计算器
package com.m.demo6;
import java.util.ArrayList;
import java.util.List;
public class MyCounter {
public static void main(String[] args) {
ArrayStack stackNum=new ArrayStack(10);//用来存放数字
ArrayStack stackOp=new ArrayStack(10);//用来存放运算符 char 和int 可以混用
String str="8888*234+12-5";
// String str="3+2*6-2";
List<String> li=numsMerge(str);
// 将字符串型转为integer型
List<Integer> list=String2Integer(li);
/**
* 1. 通过一个 index 值(索引),来遍历我们的表达式
* 2. 如果我们发现是一个数字, 就直接入数栈
* 3. 如果发现扫描到是一个符号, 就分如下情况
* 3.1 如果发现当前的符号栈为 空,就直接入栈
* 3.2 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,
* 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈,
* 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
* 4. 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
* 5.最后在数栈只有一个数字,就是表达式的结果
*
*/
// 遍历集合分别入栈:
for(int i:list) {
if(isOption(i)) {
//
// 3.1如果发现当前的符号栈为 空,就直接入栈
if(stackOp.isEmpty()) {
stackOp.push(i);
}else {
// 3.2 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,
//* 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈,
// * 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
if(opPriperty(i)<=opPriperty(stackOp.peek())) {
int num1=stackNum.pop();
int num2=stackNum.pop();
int op=stackOp.pop();
int res=result(num1,num2,op);
stackNum.push(res);
stackOp.push(i);
}else {
stackOp.push(i);
}
}
}else {
//如果我们发现是一个数字, 就直接入数栈:将字符串先转换为数字入数栈
stackNum.push(i);
// stackNum.peek();
}
}
// 4. 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
// System.out.println(stackNum);
// System.out.println(stackOp);
while(true) {
if(stackOp.isEmpty()) {
break;
}
int num1=stackNum.pop();
int num2=stackNum.pop();
int op=stackOp.pop();
int res=result(num1,num2,op);
stackNum.push(res);
}
System.out.printf("%s=%d\n",str,stackNum.peek());
}
/**
* 这个方法是将字符串中的数字合并,方便之后直接运用
* @param str 输入原始字符串
* @return 将字符串和符号分开后返回 方便实现多位数的运算
*/
public static List<String> numsMerge(String str){
// String s="723+5*7890+123";
char[] chs=str.toCharArray();
List<String> list=new ArrayList<>();
String ss="";
for(int i=0;i<chs.length;i++) {
if(chs[i]=='+'||chs[i]=='-'||chs[i]=='*'||chs[i]=='/') {
// System.out.println(ss);
list.add(ss);
list.add(String.valueOf(chs[i]));
ss="";
}else {
ss+=chs[i];
}
}
// System.out.println(ss);
list.add(ss);
// System.out.println(list);
return list;
}
/**
* 遍历集合,将元素转为int 类型,java中int 类型和char类型可以混用
* @param list
* @return
*/
public static List<Integer> String2Integer(List<String> list){
// System.out.println(list);
List<Integer> list2=new ArrayList<>();
for(String li:list) {
int i=0;
// System.out.println("li长度:"+li.length());
// System.out.println("li==*:"+(li.equals("*")));
if(li.equals("+")||li.equals("-")||li.equals("*")||li.equals("/")) {
i=li.charAt(0);
}else {
i=Integer.parseInt(li);
}
list2.add(i);
}
// System.out.println(list2);
return list2;
}
/**
* 判断是否为操作符
* @param li
* @return
*/
public static boolean isOption(int li) {
return li=='+'||li=='-'||li=='*'||li=='/';
}
/**
* op运算
* @param num1
* @param num2
* @param op
* @return
*/
public static int result(int num1,int num2,int op) {
int res=0;
switch(op) {
case '+':res=num1+num2;break;
case '-':res=num2-num1;break;
case '*':res=num2*num1;break;
case '/':res=num2/num1;break;
default:break;
}
return res;
}
public static int opPriperty(int op) {
if(op=='+'||op=='-') {
return 0;
}
return 1;
}
}