一.定义
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为先进后出表。栈可以用来在函数调用的时候存储断点,做递归时要用到栈!
二.基于数组实现栈
1.思路
1.定义数组实现栈
public class ArrayStack { private int maxSize;//栈的大小 private int[] stack;//数组模拟栈 private int top=-1;//栈顶 /*构造器*/ public ArrayStack(int maxSize){ this.maxSize = maxSize; stack = new int[maxSize]; } /*判断栈满*/ public boolean isFull(){ return top == maxSize-1; } /*判断空栈*/ public boolean isEmpty(){ return top==-1; } /*入栈*/ public void push(int value){ if (isFull()){ System.out.println("栈满"); return; } top++; stack[top]=value; } /*出栈*/ public int pop(){ if (isEmpty()){ throw new RuntimeException("空栈"); } int res = stack[top]; top--; return res; } /*遍历栈*/ public void list(){ if (isEmpty()){ System.out.println("栈空无数据"); return; } for (int i =top ; i >=0 ; i--) { System.out.printf("stack[%d]=%d ",i,stack[i]); } } }
2.进行测试
public class ArrayStackDemo { public static void main(String[] args) { ArrayStack arrayStack = new ArrayStack(4); char key = ' '; Scanner scanner = new Scanner(System.in); boolean loop = true; while (loop){ System.out.println("s(show):显示栈"); System.out.println("e(exit):退出程序"); System.out.println("a(push):添加数据"); System.out.println("g(pop):取数据"); key = scanner.next().charAt(0);//接收数据 switch (key){ case 's': arrayStack.list(); break; case 'a': System.out.println("请输入数据"); int value = scanner.nextInt(); arrayStack.push(value); break; case 'g': try { int res = arrayStack.pop(); System.out.printf("取出的数据:%d ",res); }catch (Exception e){ System.out.println(e.getMessage()); } break; case 'e': scanner.close(); loop = false; break; default: break; } } System.out.println("程序退出"); } }
三.利用栈结构实现计算器
1.思路
1.利用数组定义一个栈
public class ArrayStack2 { private int maxSize;//栈的大小 private int[] stack;//数组模拟栈 private int top=-1;//栈顶 /*构造器*/ public ArrayStack2(int maxSize){ this.maxSize = maxSize; stack = new int[maxSize]; } /*判断栈满*/ public boolean isFull(){ return top == maxSize-1; } /*判断空栈*/ public boolean isEmpty(){ return top==-1; } /*入栈*/ public void push(int value){ if (isFull()){ System.out.println("栈满"); return; } top++; stack[top]=value; } /*出栈*/ public int pop(){ if (isEmpty()){ throw new RuntimeException("空栈"); } int res = stack[top]; top--; return res; } /*遍历栈*/ public void list(){ if (isEmpty()){ System.out.println("栈空无数据"); return; } for (int i =top ; i >=0 ; i--) { System.out.printf("stack[%d]=%d ",i,stack[i]); } } /*显示栈顶元素*/ public int peek(){ return stack[top]; } /*返回运算符的优先级,优先级越大数字就越大*/ public int priority(int oper){ if (oper == '*'||oper=='/'){ return 1; }else if (oper=='+'||oper=='-'){ return 0; }else { return -1; } } /*判断是不是一个符号*/ public boolean isOper(char val){ return val=='+'||val=='-'||val=='*'||val=='/'; } /*计算方法*/ public int cal(int num1, int num2,int val){ int res = 0; switch (val){ case'+': res=num1+num2; break; case'-': res=num2-num1; break; case'*': res=num1*num2; break; case'/': res=num2/num1; break; default: break; } return res; }
2.判断运算符的优先级
public class Operation { private static int ADD=1; private static int SUB=1; private static int MUL=2; private static int DIV=2; /*返回对应的优先级*/ public static int getValue(String operation){ int res = 0; switch (operation){ case "+": res = ADD; break; case "-": res = SUB; break; case "*": res = MUL; break; case "/": res = DIV; break; default: System.out.println("运算符有误"); break; } return res; } }
3.进行测试
public class Calculator { public static void main(String[] args) { String expression = "70+2*6-4"; /*创建数栈和符号栈*/ ArrayStack2 numStack = new ArrayStack2(10); ArrayStack2 operStack = new ArrayStack2(10); //定义相关变量 String keepNum=""; int index = 0; int num1= 0; int num2= 0; int oper= 0; int res=0; char ch=' ';//将每次扫描的char保存到ch; //开始扫描 while (true){ //依次得到字符 ch = expression.substring(index,index+1).charAt(0); if (operStack.isOper(ch)){//如果是运算符 //判断栈空 if (!operStack.isEmpty()){ //处理 /*如果入栈的操作符的优先级小于或者等于栈中的操作符 * 就后,将从数栈中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 { //为空直接入符号栈 operStack.push(ch); } }else {//如果是数直接入符号栈 //numStack.push(ch-48); /*处理多位数时*/ keepNum+=ch; 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 = "";/*//清空*/ } } } /*让指针+1判断是否扫描到最后*/ index++; if (index>=expression.length()){ break; } } /*扫描完成后将数栈和符号栈中的pop对应的数和符号进行运算*/ while (true){ if (operStack.isEmpty()){//计算最后结果 break; } num1 = numStack.pop(); num2 = numStack.pop(); oper = operStack.pop(); res =numStack.cal(num1,num2,oper); numStack.push(res);//入栈 } int he = numStack.pop(); System.out.printf("表达%s = %d",expression,he); } }