上一篇我们练习了怎么手动实现一个简单的栈式结构,这一次我们通过自己实现的栈,来解决简单的四则运算表达式的计算问题。
首先贴出栈的代码:
public class MyStack {
/**
* 栈结构和ArrayList结构差不多,但它只有一个入口兼出口,不允许随机访问,也就是先进后出FIFO
*/
private String[] dataArray;
private int size;
public MyStack(){
dataArray=new String[8];
size = 0;
}
//入栈
public void push(String data){
if(size>=dataArray.length){
//如果数组已满则需要先扩容
String[] tempArray = new String[size*2];
for(int i = 0;i<dataArray.length;i++){
tempArray[i]= dataArray[i];
}
dataArray=tempArray;
}
dataArray[size]=data;
size++;
}
//出栈
public String pop(){
if(size>0){
String o = dataArray[size-1];
System.out.println(o+"出栈");
dataArray[size-1]=null;
size--;
return o;
}else{
System.out.println("栈已空,无元素可出");
return null;
}
}
//获取栈顶元素,不出栈
public String peek(){
if(size>0){
return dataArray[size-1];
}else{
System.out.println("栈已空");
return null;
}
}
public int size(){
return size;
}
public void print(){
for(int i=0;i<size;i++){
System.out.println(dataArray[i]);
}
}
/*为了方便取出算术表达式的结构,
我这里写了一个取出字符数组的方法,
正常来讲栈不应该有这个方法才对*/
public String[] getArray(){
return dataArray;
}
}
接下来我们写一个测试方法,来使用栈计算运算表达式的值
public class Test01 {
public static void main(String[] args){
//使用两个栈模拟运算简单的整数四则运算表达式,
//很初级,只考虑整数,不考虑小数,感兴趣的同学可以自己完善
String str = "31+24*15-176/11";
String jia = "+";
String jian = "-";
String cheng = "*";
String chu = "/";
//下面这两个todo是对程序健壮性的优化,不是本次练习的重点,我就不写了
//todo 如果算术表达式中含有运算符和数字以外的字符,则报错
//todo 如果相邻两个字符都是运算符,则报错
MyStack stack1 = new MyStack();//存数字
MyStack stack2 = new MyStack();//存运算符
String[] strings = splitToArray(str);
//先算乘除运算
for(int i=0;i<strings.length;i++){
if(null!=strings[i]){
if(isDigit(strings[i])){
if(cheng.equals(stack2.peek())||chu.equals(stack2.peek())){
String yunsuanfu = stack2.pop();
String num1s = stack1.pop();
Double num1=Double.valueOf(num1s);
Double num2 = Double.valueOf(strings[i]);
if(cheng.equals(yunsuanfu)){
Double tempResult = num1*num2;
stack1.push(String.valueOf(tempResult));
}else{
Double tempResult = num1/num2;
stack1.push(String.valueOf(tempResult));
}
}else{
stack1.push(strings[i]);
}
}else{
stack2.push(strings[i]);
}
}
}
//后算加减运算
while(null!=stack2.peek()){
String yunsuanfu=stack2.pop();
String num2s = stack1.pop();
Double num2 = Double.valueOf(num2s);
String num1s = stack1.pop();
Double num1 = Double.valueOf(num1s);
if(jia.equals(yunsuanfu)){
Double tempResult= num1+num2;
stack1.push(String.valueOf(tempResult));
}else{
Double tempResult= num1-num2;
stack1.push(String.valueOf(tempResult));
}
}
System.out.println(stack1.peek());
}
//将运算表达式字符串分解成数字和运算符的形式,便于下面的计算
public static String[] splitToArray(String str){
MyStack stack= new MyStack();
boolean lastOneIsDigit = true;
for(int i = 0;i<str.length();i++){
if(Character.isDigit(str.charAt(i))){
if(i==0){
stack.push(String.valueOf(str.charAt(i)));
}else{
if(lastOneIsDigit){
String lastDigitStr = stack.pop();
double lastDigit = Double.parseDouble(lastDigitStr);
stack.push(String.valueOf(lastDigit*10+ Double.parseDouble(String.valueOf(str.charAt(i)))));
}else{
stack.push(String.valueOf(str.charAt(i)));
lastOneIsDigit=true;
}
}
}else{
stack.push(String.valueOf(str.charAt(i)));
lastOneIsDigit = false;
}
}
return stack.getArray();
}
//使用正则表达式判断一个字符串是不是数字
public static boolean isDigit(String str){
return str.matches("-?\\d+(\\.\\d+)?");
}
}
最后我们运算测试类,可以得到表达式的值上375