当你依次访问完一串a-b-c页面之后,点击浏览器的后退按钮,就可以查看之前浏览的页面a和b。当你后退到页面a,点击前进按钮,就可以重新查看页面b和c。但是,如果你后退到页面b后,点击了新的页面d,就无法再通过前进后退功能查看页面c了。
要实现上述功能,就需要用到“栈”这个数据结构。
一. 简介
“栈”是一种有特定规则的数据结构,当某个数据集合只设计在一端进行插入和删除数据的操作,并且满足后进先出,先进后出的特性,我们就应该首选“栈”这种数据结构。
从功能上来说,数组或链表可以替代栈,但是,特定的数据结构是对特定场景的抽象,而且,数据或链表暴露了太多操作接口,操作上的确是灵活自由,但这也导致在使用时就比较不可控,也就更加容易出错。
二. 栈的实现
栈包含两个操作-----出栈和入栈
栈包含两种实现------用数组实现的顺序栈和用链表实现的链式栈
// 基于数组实现的顺序栈
public class ArrayStack {
private String[] items; // 数组
private int count; // 栈中元素个数
private int n; // 栈的大小
// 初始化数组,申请一个大小为 n 的数组空间
public ArrayStack(int n) {
this.items = new String[n];
this.n = n;
this.count = 0;
}
// 入栈操作
public boolean push(String item) {
// 数组空间不够了,直接返回 false,入栈失败。
if (count == n) return false;
// 将 item 放到下标为 count 的位置,并且 count 加一
items[count] = item;
++count;
return true;
}
// 出栈操作
public String pop() {
// 栈为空,则直接返回 null
if (count == 0) return null;
// 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一
String tmp = items[count-1];
--count;
return tmp;
}
}
栈的时间空间复杂度均为O(1)
支持动态扩容的顺序栈时间复杂度:
三. 栈的实践应用
- 程序运行时的栈帧
- 表达式求值
- 括号匹配
解答开篇:
在开篇的浏览器应用中,我们使用两个栈X和Y。
顺序查看时:
后退时:
开启新网页时: