栈练习(1)

64 阅读4分钟

“携手创作,共同成长!开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

案例:使用栈来实现综合计算机功能

思路分析:

1.使用栈完成表达式的计算

1) 通过index(一个索引值)来进行遍历表达式,

2) 设置两个栈,一个栈存放数据,一个栈存放运算符。若遍历的是数据就入数据栈中

3) 若遍历的是运算符就要分情况再入运算符栈中

a. 如果发现当前的符号栈为空,就直接入栈

b. 如果符号栈有操作符,就进行比较,如果当前的操作符的操作符的优先级小于或者等于栈中的操作符,数栈中pop出两个数,再在从符号栈中pop出一个运算符,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈,

c. 如果当前的操作符的操作符的优先级大于栈中的操作符,就直接入符号栈

4)当表达式扫描完毕后,就顺序的从数栈和符号栈中pop出相应的数和符号,并进行运算

5)最后数栈只有一个数字,就是表达式的结果

代码实现:

    public static void main(String[] args) {  
        //开始完成表达式的运算  
        String  experssion="3+2*6-2";  
        //创建两个栈,一个是数栈,一个是运算符栈  
        ArrayStack2 numstack = new ArrayStack2(10);  
        ArrayStack2 operstack = new ArrayStack2(10);  
        //定义相关变量  
        int index=0; //用于扫描  
        int num1=0;  
        int num2=0;  
        int oper=0;  
        int res=0;  
        char ch=' '; //将每次扫描得到的char保存到ch中  
        //先开始while循环的扫描expression,直到没有运算符和数字结束  
        while (true){  
            //依次得到expression表达式中的每一个字符  
            //使用substring即使取出来了也是一个字符的字符串,还需要用charAt(0)将其变成字符  
            ch=experssion.substring(index,index+1).charAt(0);  
            //判断是字符还是数字  
            if (operstack.isOper(ch)){  //当字符为运算符时候  
                //判断字符是否为空  
                if (operstack.isNull()){   //如果为空会直接入栈  
                    operstack.push(ch);  
                } else{ //如果符号栈有操作符,就进行比较,如果当前的操作符的操作符的优先级小  
                    // 于或者等于栈中的操作符,数栈中pop出两个数,再在从符号栈中pop出一个运算符,  
                    // 进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈,  
                    if(operstack.priority(ch)<=operstack.priority(operstack.peek())){  
                        num1=numstack.pop();  
                        num2=numstack.pop();  
                        oper=operstack.pop();  
                        res=numstack.cal(num1,num2,oper);  
                        numstack.push(res);  
                        operstack.push(ch);  
                    } else {  //如果当前的操作符的操作符的优先级大于栈中的操作符,就直接入符号栈  
                        operstack.push(ch);  
                    }  
                }  
            } else{  //若是数则会入栈,因为字符本身有ASCII码,所以要减去本身的值  
                    numstack.push(ch-48);  
            }  
            //让index+1,并判断扫描experssion是否结束  
            index++;  
            //因为每次执行完就多了一,所以index的值会不断的增加,可以与表达式的长度进行比较  
            if (index>=experssion.length()){  
                break;  
            }  
        }  
        //当表达式扫描完毕后,就顺序的从数栈和符号栈中pop出相应的数和符号,并进行运算  
        while (true){  
            //如果符号栈为空,则数栈就会只有一个值,也就是结果  
            if (operstack.isNull())  
            {break; }  
           else{ num1=numstack.pop();  
            num2=numstack.pop();  
            oper=operstack.pop();  
            res=numstack.cal(num1,num2,oper);  
            numstack.push(res);  
           }  
        }  
        //将数栈最后的值出栈,就是结果  
res=numstack.pop();  
System.out.println("表达式的值为:"+experssion+'='+res);

 

  
    }  
}  
//先创建一个栈,并在其中加入返回优先级的函数,优先级的大小是由自己设置的,  
// 这里采用的是数字越大代表的优先级越高,再在其中加入数据运算的函数  
class ArrayStack2{  
    private int Maxsize;  
    private int[] stack;  
    private int top=-1;  
  
    public ArrayStack2(int maxsize) {  
        Maxsize = maxsize;  
        stack=new int[maxsize];  
    }  
    //判断是否为满  
    public boolean isFull(){  
        return top==Maxsize-1;  
    }  
    //判断是否为空  
    public boolean isNull(){  
        return top==-1;  
    }  
    //入栈  
    public void push(int value){  
        //判断栈是否满了,满了无法再入栈  
        if(isFull()){  
            System.out.println("栈满了");  
            return;  
        }  
        top++;  
        stack[top]=value;  
    }  
    //出栈  
    public int  pop(){  
        //判断栈是否为空,为空将无法出栈  
        if(isNull()){  
            //通过抛出程序运行异常来显示错误,该运行异常不需要捕获,同时运行异常抛出的同时会结束运行  
            throw new RuntimeException("栈空,没有数据");  
        }  
        int value=stack[top];  
        top--;  
        return value;  
    }  
    //显示栈的情况,需要从栈顶开始开始查询数据  
    public void list(){  
        if(isNull()){  
            System.out.println("栈空,没有数据");  
        }  
        for (int i = top; i >= 0; i--) {  
            System.out.printf("stack[%d]=%d\n",i,stack[i]);  
        }  
    }  
    //返回优先级的函数  
    //数字越大代表的优先级越高  
    public int priority(int oper){ //在java中字符本身代表一个数值,可以在数值和字符之间进行转换  
        if (oper=='*'||oper=='/'){  
            return 1;  
        } else if (oper=='+'||oper=='-'){  
            return 0;  
        } else  return -1; //这里只有加减乘除的运算  
    }  
    //判断运算符  
    public boolean isOper(int oper){  
        return oper=='+'||oper=='-'||oper=='*'||oper=='/';  
    }  
    //数据运算的函数  
    public int cal(int num1,int num2,int oper){  
        int res=0; //用于存放计算结果  
        switch (oper){ //要注意数的顺序,因为栈是先进后出,所以本身后面的数应该放在前面  
            case '+':  
                res=num2+num1;break;  
            case '-':  
                res=num2-num1;break;  
            case '*':  
                res=num2*num1;break;  
            case '/':  
                res=num2/num1;break;  
            default:  
                break;  
        }  
        return res;  
    }  
    //可以返回当前的栈顶值,但是不会进行改变任何操作  
    public int peek(){  
        return stack[top];  
    }  
}