栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表.允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom).
基本介绍
1. 栈是一个先入后出(FILO First In Last Out)的有序列表
2.栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表.允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom).
3.根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除.
栈的应用场景
1.子程序的调用:在调往子程序前,会先将下个指令的地址存到栈中,直到子程序执行完后再将地址取出,以回到原来的程序.
2.处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数\区域变量等数据存入堆栈中.
3.表达式转换(中缀表达式转后缀表达式)与求值(实际解决).
4.二叉树的遍历.
5.图形的深度优先(depth-first)搜索算法.
栈结构实现案例
- packagecom.structures.stack;
- importjava.util.Scanner;
- publicclassArrayStackDemo{
- publicstaticvoidmain(String[]args){
- ArrayStackstack=newArrayStack(4);
- Stringkey="";
- booleanloop=true;
- Scannerscanner=newScanner(System.in);
- while(loop){
- System.out.println("show:显示栈");
- System.out.println("exit:退出程序");
- System.out.println("push:添加数据到栈(入栈)");
- System.out.println("pop:从栈取出数据(出栈)");
- key=scanner.next();
- switch(key){
- case"show":
- stack.list();
- break;
- case"push":
- System.out.println("请输入一个数");
- intvalue=scanner.nextInt();
- stack.push(value);
- break;
- case"pop":
- try{
- intres=stack.pop();
- System.out.println("出栈的数据%d\n"+res);
- }catch(Exceptione){
- System.out.println(e.getMessage());
- }
- break;
- case"exit":
- scanner.close();
- loop=false;
- break;
- }
- }
- System.out.println("程序退出");
- }
- }
- //定义一个类表示栈结构
- classArrayStack{
- privateintmaxSize;//栈的大小
- privateint[]stack;//数组模拟栈,数据就放入该数组
- privateinttop=-1;//top表示栈顶,初始化-1
- publicArrayStack(intmaxSize){
- this.maxSize=maxSize;
- stack=newint[this.maxSize];
- }
- //判断是否栈满
- publicbooleanisFull(){
- returntop==maxSize-1;
- }
- //判断是否栈空
- publicbooleanisEmpty(){
- returntop==-1;
- }
- //入栈
- publicvoidpush(intvalue){
- if(isFull()){
- System.out.println("栈满");
- return;
- }
- top++;
- stack[top]=value;
- }
- //出栈
- publicintpop(){
- if(isEmpty()){
- thrownewRuntimeException("栈空");
- }
- intvalue=stack[top];
- top--;
- returnvalue;
- }
- //显示栈的情况[遍历栈]
- publicvoidlist(){
- if(isEmpty()){
- System.out.println("栈空,没有数据~~");
- return;
- }
- for(inti=top;i>=0;i--){
- System.out.printf("stack[%d]=%d\n",i,stack[i]);
- }
- }
- }
使用栈完成表达式的计算(中缀表达式)
准备两个栈,数字栈和符号栈.
1.通过一个index值(索引),来遍历表达式.
2.如果发现是一个数字就直接入数字栈.
3.如果是一个符号,分情况考虑如果当前符号栈为空,就直接入站.如果符号栈有操作符,就进行比较.
- 如果当前操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop两个数,再从符号栈中pop出一个字符,进行运算,将得到结果入数栈,然后当前操作符入符号栈.
- 如果当前的操作符的优先级大于栈中的操作符,就直接入栈.
4.当表达式扫描完毕,就顺序地从数栈和符号栈中pop出相应的数和符号,并运行.
5.最后在数字栈只有一个数字,就是表达式的结果.
- packagecom.structures.stack;
- publicclassCalculator{
- publicstaticvoidmain(String[]args){
- //表达式
- Stringexpression="700+2*6-2";
- //数栈
- ArrayStack2numStack=newArrayStack2(10);
- //符号栈
- ArrayStack2operStack=newArrayStack2(10);
- intindex=0;//用于扫描
- intnum1=0;
- intnum2=0;
- intoper=0;
- intres=0;
- charch='';//将每次扫描得到的char保存到ch
- StringkeepNum="";//用于拼接多位数
- while(true){
- 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=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{
- //当处理多位数时,不能立即入栈.
- keepNum+=ch;
- //如果ch是expression的最后一位
- if(index==expression.length()-1){
- numStack.push(Integer.parseInt(keepNum));
- }else{
- if(operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
- numStack.push(Integer.parseInt(keepNum));
- keepNum="";
- }
- }
- }
- index++;
- //扫遍到最后就退出
- if(index>=expression.length()){
- break;
- }
- }
- while(true){
- if(operStack.isEmpty()){
- break;
- }
- num1=numStack.pop();
- num2=numStack.pop();
- oper=operStack.pop();
- res=numStack.cal(num1,num2,oper);
- numStack.push(res);
- }
- System.out.printf("表达式%s=%d\n",expression,numStack.pop());
- }
- }
- classArrayStack2{
- privateintmaxSize;//栈的大小
- privateint[]stack;//数组模拟栈,数据就放入该数组
- privateinttop=-1;//top表示栈顶,初始化-1
- publicArrayStack2(intmaxSize){
- this.maxSize=maxSize;
- stack=newint[this.maxSize];
- }
- //返回当前栈顶的值,不是pop
- publicintpeek(){
- returnstack[top];
- }
- //判断是否栈满
- publicbooleanisFull(){
- returntop==maxSize-1;
- }
- //判断是否栈空
- publicbooleanisEmpty(){
- returntop==-1;
- }
- //入栈
- publicvoidpush(intvalue){
- if(isFull()){
- System.out.println("栈满");
- return;
- }
- top++;
- stack[top]=value;
- }
- //出栈
- publicintpop(){
- if(isEmpty()){
- thrownewRuntimeException("栈空");
- }
- intvalue=stack[top];
- top--;
- returnvalue;
- }
- //显示栈的情况[遍历栈]
- publicvoidlist(){
- if(isEmpty()){
- System.out.println("栈空,没有数据~~");
- return;
- }
- for(inti=top;i>=0;i--){
- System.out.printf("stack[%d]=%d\n",i,stack[i]);
- }
- }
- //返回运算符的优先级,数字越大则优先级越高.
- //假定目前操作符只有+-*/
- publicintpriority(intoper){
- if(oper=='*'||oper=='/'){
- return1;
- }elseif(oper=='+'||oper=='-'){
- return0;
- }else{
- return-1;
- }
- }
- //判断是不是一个运算符
- publicbooleanisOper(charval){
- returnval=='+'||val=='-'||val=='*'||val=='/';
- }
- //计算方法
- publicintcal(intnum1,intnum2,intoper){
- intres=0;
- switch(oper){
- case'+':
- res=num1+num2;
- break;
- case'-':
- res=num2-num1;//注意顺序
- break;
- case'*':
- res=num1*num2;
- break;
- case'/':
- res=num2/num1;//注意顺序
- break;
- }
- returnres;
- }
- }
【编辑推荐】
- 凉凉,老板叫我开发一个简单的工作流引擎...
- Windows10将迎来翻天覆地变化!今年第一个更新来了
- 2021年将迎来六大网络安全趋势
- Windows 10近年最大改进!Windows10 21H2新特性抢先看
- 小爱同学竟然推出了PC版?带你体验电脑版小爱
转载请说明出处
知优网 » Java编程内功-数据结构与算法「栈(Stack)」(栈结构及运算的实现)
知优网 » Java编程内功-数据结构与算法「栈(Stack)」(栈结构及运算的实现)