- 1.栈(Stack)
- 2.栈空间
- 3.栈的接口设计
- 4.实现:
- 4.1.直接继承ArrayList,复用其中的一些方法
- 4.2.将ArrayList作为Stack的一个私有属性
- 5.Java官方提供的栈:java.util.Stack
- 6.栈的应用 - 浏览器的前进后退
-
栈是一种特殊的线性表,只能在一端进行操作。
往栈中添加元素的操作,一般叫做push,入栈。
从栈中移除元素的操作,一般叫做pop,出栈(只能移除栈顶元素,也叫做弹出栈顶元素)。
后进先出的原则:Last In First Out, LIFO
注意:这里所说的栈和内存中的栈空间是两个不同的概念
1.进程内存映像
进程内存映像即用户进程的虚拟空间,一共包含了4个部分的内容:
- text代码段:是只读的,存放要执行的指令。
- data数据段:存放全局或静态变量。
- heap堆:运行时分配的内存(如用malloc,new函数申请的内存)
- statck栈:存放局部变量和函数返回地址(所以说,调用一个方法/函数,即为这个方法开辟一个栈空间)
-
思考:栈的内部实现是否可以直接利用以前学过的数据结构呢?
因为栈的操作,主要就是对栈顶的元素进行出栈、入栈的操作。而动态数组和链表对尾部元素操作的时间复杂度都是O(1)。所以这两个都可以实现,且效率差不多。
- 1.代码实现
public class Stackextends ArrayList { //直接继承自ArrayList // public int size() { // return 0; // } //直接继承自ArrayList // public boolean isEmpty() { // return false; // } public void push(E element) { add(element); } public E pop() { return remove(size-1); } public E top() { return get(size - 1); } }
-
2.直接继承的坏处:
继承了ArrayList中的其他方法,这些方法根本不符合Stack只能从栈顶出栈入栈的属性。比如:
- 1.代码实现:这样更合理一些
public class Stack5.Java官方提供的栈:java.util.Stack{ private List list = new ArrayList<>(); public int size() { return list.size(); } public boolean isEmpty() { return list.isEmpty(); } public void push(E element) { list.add(element); } public E pop() { return list.remove(list.size()-1); } public E top() { return list.get(list.size() - 1); } }
-
继承自Vector:public class Stack
extends Vector {} -
Vector和ArrayList的实现很相似,最大的区别在于其是一个线程安全的线性表:
public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); } } -
java.util.Stack中提供的方法:
其中peek()就是top():访问栈顶元素
1.浏览器的前进和后退是通过两个栈结构来实现的。
-
浏览器依次访问3个网站:入栈A
-
后退两次:栈A出栈两次,栈B入栈2次
-
在前进:栈A入栈,栈B出栈
-
访问一个新的网站:栈A入栈,栈B清空



