第6讲 栈

112 阅读2分钟

栈的英文为(stack)

栈是一个先入后出(FILO-First In Last Out)的有序列表。

栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。

根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。

数组模拟栈代码:

public class ArrayStackDemo {
    public static void main(String[] args) {
        ArrayStack arrayStack = new ArrayStack(3);
        arrayStack.push(1);
        arrayStack.push(2);
        arrayStack.push(3);
        arrayStack.display();
        System.out.println(arrayStack.pop());
        arrayStack.pop();
        System.out.println("----------");
        arrayStack.display();
    }

}

class ArrayStack{
    private int maxSize;
    private int[] stack;//数据区域
    private int top=-1;

    public ArrayStack(int maxSize) {
        this.maxSize=maxSize;
        stack=new int[maxSize];
    }

    public void push(int v){
        if(top==maxSize){
            throw new RuntimeException("栈已满");
        }
        top++;
        stack[top]=v;
    }

    public int pop(){
        if(top==-1){
            throw new RuntimeException("栈为空");
        }
        int val=stack[top];
        top--;
        return val;
    }

    public void display(){
            int index=top;
            while (index>-1){
                System.out.println(stack[index]);
                index--;
          }
    }
}

使用栈来实现综合计算器-自定义优先级

public class Calculator {
    public static void main(String[] args) {
        //表达式
        String expression="7*2*2-5+1-5+3-4";
        //创建2个栈 数栈 符号栈
        ArrayStack2 numberStack = 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=' ';
        String keepNubmer="";

        while (true){
            //依次得到expression的每一个字符
            ch = expression.substring(index, index + 1).charAt(0);
            //运算符
            if(operStack.isOper(ch)){
                //判断符号栈是否为空 为空直接入栈
               if(operStack.isEmpty()){
                   operStack.push(ch);
               }else {
                   //符号栈不为空 进行比较,如果当前优先级小于栈中的优先级就让前面先执行
                   if(operStack.priority(ch)<=operStack.priority(operStack.peek())){
                       num1=numberStack.pop();
                       num2=numberStack.pop();
                       oper=operStack.pop();
                       res=numberStack.cal(num1,num2,oper);
                       //运算结果入数栈
                       numberStack.push(res);
                       //当前操作符入栈
                       operStack.push(ch);
                   }else {
                       //小于 直接入栈
                       operStack.push(ch);
                   }
               }
            }else {
//                numberStack.push(ch-48);
                //发现数时不能立即入栈 存在多位数情况 向后继续扫描直到符号出现
                keepNubmer+=ch;
                //如果ch已经是最后一位 直接入栈
                if(index==expression.length()-1){
                    numberStack.push(Integer.parseInt(keepNubmer));
                }else {
                    //判断下一位是否为数字 如果是运算符 则入栈
                    if(operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                        //如果后一位是运算符 入栈
                        numberStack.push(Integer.parseInt(keepNubmer));
                        //清空
                        keepNubmer="";
                    }
                }
            }
            index++;
            //判断是否扫描到最后
            if(index>=expression.length()){
                break;
            }
        }
        //表达式扫描完毕 顺序从数栈和符号栈pop出对应的数和符号 运行
        while (true){
            if(operStack.isEmpty()){
                break;
            }
            num1=numberStack.pop();
            num2=numberStack.pop();
            oper=operStack.pop();
            res=numberStack.cal(num1,num2,oper);
            //运算结果入数栈
            numberStack.push(res);
        }
        //数栈中的最后一个数pop出来就是结果
        int pop = numberStack.pop();
        System.out.printf("表达式%s=%d",expression,pop);
    }
}


//先创建一个Stack
class ArrayStack2{
    private int maxSize;
    private int[] stack;//数据区域
    private int top=-1;

    public ArrayStack2(int maxSize) {
        this.maxSize=maxSize;
        stack=new int[maxSize];
    }

    public void push(int v){
        if(top==maxSize){
            throw new RuntimeException("栈已满");
        }
        top++;
        stack[top]=v;
    }

    public boolean isEmpty(){
      return top==-1;
    }

    public int pop(){
        if(top==-1){
            throw new RuntimeException("栈为空");
        }
        int val=stack[top];
        top--;
        return val;
    }

    //返回栈顶值
    public int peek(){
        return stack[top];
    }

    public void display(){
        int index=top;
        while (index>-1){
            System.out.println(stack[index]);
            index--;
        }
    }

    //返回运算符的优先级 数字越大 优先级越高
    public int priority(int opr){
        if(opr=='*'||opr=='/'){
            return 1;
        } else if (opr == '+' || opr == '-') {
            return 0;
        }else {
            return -1;
        }
    }

    //判断是不是运算符
    public boolean isOper(char val){
        return val=='*'|| val=='/'|| val=='+'|| val=='-';
    }

    //计算方法
    public int cal(int num1,int num2,int opr){
        int res=0;//用于存放结果
        switch (opr){
            case '+':
                res=  num1 + num2;
                break;
            case '-':
                res= num2 - num1;
                break;
            case '*':
                res= num1 * num2;
                break;
            case '/':
                res= num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}