一.栈的实际需求
请输入一个表达式 计算式:[7*2*2-5+1-5+3-3] 点击计算
(不是像你想的分别创建几个变量接受,他是一个整体,即他是用户输入的一个字符串.)
请问: 计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们看这个算式 7 * 2 * 2 - 5, 但是计算机怎么理解这个算式的(对计算机而言,它接收到的就是一个字符串),所以引出我们讨论的问题。-> 栈
二.栈的介绍
1)栈的英文为(stack)
2)栈是一个先入后出(FILO-First In Last Out)的有序列表。
3)栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。 4)根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除
5)出栈为pop,入栈为push,如下图:
三.栈的应用场景
3.1子程序的调用
在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
3.2处理递归调用
和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
3.3表达式的转换与求值
1)中缀表达式转后缀表达式之间的转换
2)实际解决前面提到的栈的实际需求
3.4二叉树的遍历
3.5图形的深度优先(depth一first)搜索法
后续博客的章节我们会一一完成这些应用场景!!!
四.栈的快速入门
4.1用数组模拟栈的使用
1)由于栈是一种有序列表, 所以可以使用数组的结构来储存栈的数据内容, 下面我们就用数组模拟栈的出栈,入栈等操作
4.1.1思路分析
1)首先定义一个变量top,表示栈顶,初始化为-1(因为我们是用数组实现栈的,数组第一个值的索引为0,即当我们压入栈时,top++,刚好符合数组的索引)
2)当我们pop时,定义一个临时变量temp,temp = stack[top],top--
3)当我们push时,top++,stack[top] = value
4.1.2代码实现
package zy.stack;
import java.util.Scanner;
/**
* @author 十三
* @version 1.0
*/
public class StackDemo {
public static void main(String[] args) {
boolean loop = true;
String key = "";
Stack stack = new Stack(4);
Scanner scanner = new Scanner(System.in);
while (loop){
System.out.println("pop:将数据弹出栈");
System.out.println("push:将数据压入栈");
System.out.println("show:显示栈内元素");
System.out.println("exit:退出程序");
key = scanner.next();
switch (key){
case "pop":
try {
int temp = stack.pop();
System.out.printf("弹出的元素为\n",temp);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case "push":
System.out.println("请输入数据");
int value = scanner.nextInt();
stack.push(value);
break;
case "show":
stack.show();
break;
case "exit":
loop = false;
scanner.close();
break;
default:
System.out.println("请输入正确的指令");
break;
}
}
}
}
//先定义一个stack类,里面包含pop,push等方法
class Stack{
private int maxSize;
private int[] stack;
private int top = -1;
public Stack(int maxSize) {
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
// 判断栈是否满
public boolean isFull(){
return top==maxSize;
}
// 判断栈是否为空
public boolean empty(){
return top==-1;
}
// pop操作
public int pop(){
if (empty()){
throw new RuntimeException("栈空,无法pop");
}
int temp;
temp = stack[top];
top--;
return temp;
}
// push操作
public void push(int value){
if (isFull()){
System.out.println("栈满了,无法push");
return;
}
top++;
stack[top]=value;
}
//展示栈里面的元素,但要逆着展示
public void show(){
if (empty()){
System.out.println("栈空");
return;
}
for (int i= top;i!=-1;i--){
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}
4.1.3结果测试
ok,已用数组完成对栈的模拟,除了用数组之外,也可以用链表完成对栈的使用
如果想要加深对栈的理解,博主建议用 单链表完成栈的使用
五.小结
1)首先栈的应用场景很多,有处理递归调用,表达式的转换,深度优先等,他们都挺重要的,不过后面会详细完成表达式的转换
2)栈的特点就是先进后出,即 FILO
3)入栈为push,出栈为pop,很形象