栈的一个实际需求:请输入一个表达式,计算式:[7*2*2-5+1-5+3-3]
点击计算【如下图】
![栈](../../assets/img/formul.51e03b5a.png)
请问:计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们看这个算式 7*2*2-5...
, 但是计算机怎么理解这个算式的(对计算机而言,它接收到的就是一个字符串),就是下面要学习的栈;
# 一、栈的介绍
【1】栈的英文为stack
;
【2】栈是一个先入后出FILO-First In Last Out
的有序列表;
【3】栈stack
是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶Top
,另一端为固定的一端,称为栈底Bottom
;
【4】根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除;
【5】出栈pop
和入栈push
的概念(如图所示)
![栈](../../assets/img/pop.467ea7a4.png)
# 二、栈的应用场景
【1】子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
【2】处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
【3】表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。
【4】二叉树的遍历。
【5】图形的深度优先depth一first
搜索法。
# 三、栈的快速入门
【1】用数组模拟栈的使用,由于栈是一种有序列表, 当然可以使用数组的结构来储存栈的数据内容, 下面我们就用数组模拟栈的出栈,入栈等操作。
【2】实现思路分析,并画出示意图:定义一个栈顶元素Top默认为-1,随着数据的增加不断的递增。当获取元素时Top递减。
![栈](../../assets/img/max.4f850dd9.png)
【3】通过数组模拟栈的功能,代码如下:
package com.algorithms;
/**
* 栈功能模拟 on 2019/10/30 0030.
*/
public class Stack {
//栈的大小
private int maxSize;
//数组模拟栈,数据放在该数组中
private int[] stack;
//栈顶元素
private int top = -1;
//构造器
public Stack(int maxSize){
this.maxSize = maxSize;
stack = new int[maxSize];
}
//判断栈是否已经存满
public boolean isFull(){
return maxSize-1 == top;
}
//向栈中push 元素
public void push(int num){
if(!isFull()){
stack[++top] = num;
}else{
throw new RuntimeException("栈已满");
}
}
//判断栈是否为空
public boolean isNull(){
return top == -1;
}
//从栈中获取元素
public int pop(){
if(!isNull()){
return stack[top--];
}else{
throw new RuntimeException("栈为空");
}
}
//遍历栈中的元素
public void list(){
for (int i=top;i>=0;i--){
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
public static void main(String[] args) {
Stack stack = new Stack(3);
stack.push(1);
stack.push(2);
stack.push(3);
//Exception in thread "main" java.lang.RuntimeException: 栈已满
//stack.push(0);
/*
stack[2]=3
stack[1]=2
stack[0]=1
*/
stack.list();
// 3
System.out.printf(stack.pop()+"");
stack.pop();
stack.pop();
//stack.pop();
stack.list();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 四、经典案例
对文章开始提出的计算需求,通过栈进行解决:计算式:[7*2*2-5+1-5+3-3]
点击计算
实现思路:
① 通过index
下标遍历表达式的值;
② 如果发现是数字,就直接入数字栈;
③ 如果发现是符号则判断当前的符号栈是否为空,空则直接入栈。否则需要将当前符号与栈顶符号进行优先级比较,如果当前优先级低于栈顶优先级,就需要从数字栈中pop
出前两个数字,再从符号栈中pop
出栈顶符号,进行计算并将结果push
到数字栈,继续比较当前符号与栈中的优先级,如果大于栈中的优先级则直接入符号栈;
④ 如果表达式插入完毕后,就顺序的从数字栈和符号栈获取元素,进行计算;
⑤ 正常情况下,最后在数栈中会保留一个数字,就是表达式的结果;