今天跟大家一起学习一种数据结构,栈。
(1)栈的英文名为stack。
(2)栈是一个现先入后出的有序链表。
(3)栈(stack)是限制线性表中,元素的插入和删除只能在线性表的同一端进行的一种特殊线性表,允许插入和删除的一端,为变化的一端,称为栈顶,另一端为固定的一端,称为栈底。
(4)根据栈的定义可知,最先放入栈中的元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
而栈的应用场景也有很多,举几个例子:
(1)子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中
(2)处理递归调用:和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数,区域变量等数据存入堆栈中
(3)表达式的转换与求值
(4)二叉树的遍历,这个之后的文章会提到
(5)图的深度遍历优先
下面我们用一个实际的例子,来用数组模拟栈的使用(由于栈是一种有序列表,因此可以使用数组的结构来存储栈的数据内容)。
思路分析:
(1)使用数组来模拟栈
(2)定义一个top来表示栈顶,初始化为-1
(3)入栈的操作,当有数据加入栈时,top++,stack[top]=data;
(4)出栈的操作top--;
从思路可写代码:
首先我们要定义一个ArrayStack类来表示栈,并且初始化,初始化是,只要输入maxSize即可,因此类中的变量都是定义为私有的private,如果想在主函数中调用maxSize和数组stack,就需要初始化。
classArrayStack{publicArrayStack(intmaxSize){this.maxSize=maxSize;stack=newint[this.maxSize];}privateintmaxSize;//栈的大小privateint[]stack;//数组,数组模拟栈,数据就放在该数组中privateinttop=-1;//top表示栈顶,初始化为-1}
之后按照思路分别写出入栈和出栈的代码:
//入栈publicvoidpush(intvalue){//先判断栈是否满if(isFull()){System.out.println("栈满");return;}top++;stack[top]=value;}//出栈-pop,将栈顶的数据返回publicintpop(){if(isEmpty()){//抛出异常thrownewRuntimeException("栈空,没有数据");}intvalue=stack[top];top--;returnvalue;}
之后我们需要在取出数据时,判断栈是否为空,在添加数据时,由于是数组栈,需要判断栈是否满。
//栈满publicbooleanisFull(){returntop==maxSize-1;}//栈空publicbooleanisEmpty(){returntop==-1;}
然后我们还需要写出遍历显示栈中的内容:
//显示栈的情况(遍历栈)publicvoidlist(){if(isEmpty()){System.out.println("栈空,没有数据");return;}for(inti=top;i=0;i--){System.out.println("stack["+i+"]="+stack);}}
最后附上测试用例,和全部数组栈的代码,同样,这里也写了一个小菜单,当输入exit时,结束程序:
/**Tochangethislicenseheader,chooseLicenseHeadersinProjectProperties.*Tochangethistemplatefile,chooseTools
Templates*andopenthetemplateintheeditor.*/packagestack;importjava.util.Scanner;/****
authorAdministrator*/publicclassArrayStackDemo{publicstaticvoidmain(String[]args){//创建一个ArrayStack对象ArrayStackstack=newArrayStack(4);Stringkey="";booleanloop=true;Scannerinput=newScanner(System.in);while(loop){System.out.println("show:显示栈");System.out.println("exit:退出程序");System.out.println("push:添加数据到栈");System.out.println("pop:从栈中取数据");System.out.println("请输入你的选择");key=input.next();switch(key){case"show":stack.list();break;case"push":System.out.println("请输入一个数");intvalue=input.nextInt();stack.push(value);break;case"pop":try{intres=stack.pop();System.out.println("出栈的数据是"+res);}catch(Exceptione){System.out.println(e.getMessage());}break;case"exit":input.close();loop=false;break;default:break;}}}}//定义一个ArrayStack类表示栈classArrayStack{publicArrayStack(intmaxSize){this.maxSize=maxSize;stack=newint[this.maxSize];}privateintmaxSize;//栈的大小privateint[]stack;//数组,数组模拟栈,数据就放在该数组中privateinttop=-1;//top表示栈顶,初始化为-1//栈满publicbooleanisFull(){returntop==maxSize-1;}//栈空publicbooleanisEmpty(){returntop==-1;}//入栈publicvoidpush(intvalue){//先判断栈是否满if(isFull()){System.out.println("栈满");return;}top++;stack[top]=value;}//出栈-pop,将栈顶的数据返回publicintpop(){if(isEmpty()){//抛出异常thrownewRuntimeException("栈空,没有数据");}intvalue=stack[top];top--;returnvalue;}//显示栈的情况(遍历栈)publicvoidlist(){if(isEmpty()){System.out.println("栈空,没有数据");return;}for(inti=top;i=0;i--){System.out.println("stack["+i+"]="+stack);}}}运行截图如下,从显示数据中,我们可以看到栈先入后出的特性:
琢磨先生DataBase