栈
栈是存放对象的一种特殊容器,在插入与删除对象时,这种结构遵循后进先出(Last-in-first-out,LIFO)的原则--也就是说,对象可以任意插入栈中,但每次取出的都是此前插入的最后一个对象。 比如一摞椅子,只能将最顶端的椅子移出,也只能将新椅子放到最顶端--这两种操作分别称作入栈(Push)和退栈(Pop)。
栈是最基本的数据结构之一,在实际应用中几乎无所不在。 例如,网络浏览器会将用户最近访问过的地址组织为一个栈: 用户每访问一个新页面,其地址就会被存放至栈顶; 而用户每次按下“Back”按钮,最后一个被记录下的地址就会被清除掉。 再如,当今主流的文本编辑器大都支持编辑操作的历史记录功能: 用户的编辑操作会被依次记录在一个栈中; 一旦出现误操作,用户只需按下“Undo”按钮, 即可撤销最近一次操作并回到此前的编辑状态。
由于栈的重要性,在Java 的java.util 包中已经专门为栈结构内建了一个类--java.util.Stack
栈ADT(AbstractDataType)
作为一种抽象数据类型,栈必须支持以下方法:
操作方法 | 功能描述 |
---|---|
push(x) | 将对象x 压至栈顶 输入:一个对象 输出:无 |
pop() | 若栈非空,则将栈顶对象移除,并将其返回否则,报错 输入:无 输出:对象 |
getSize() | 返回栈内当前对象的数目 输入:无 输出:非负整数 |
isEmpty() | 检查栈是否为空 输入:无 输出:布尔标志 |
top() | 若栈非空,则返回栈顶对象(但并不移除)否则,报错 输入:无 输出:栈顶对象 |
基于数组的简单实现
package datastructure.stack;
public class FireStack {
private int size;
private Integer[] data;
public FireStack(){
data = new Integer[10];
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return this.size == 0;
}
public void push(Integer element){
//考虑扩容
data[size++] = element;
}
public Integer pop(){
if (isEmpty()){
throw new IndexOutOfBoundsException("-1");
}
int result = data[--size];
data[size] = null;
return result;
}
public Integer top(){
if (isEmpty()){
throw new IndexOutOfBoundsException("-1");
}
return data[size-1];
}
public static void main(String[] args) {
FireStack fireStack = new FireStack();
fireStack.push(0);
fireStack.push(1);
fireStack.push(2);
fireStack.push(3);
int length = fireStack.size;
for (int i = 0; i < length; i++) {
System.out.println(fireStack.pop());
}
}
}
测试结果
3
2
1
0
面试中关于栈的常见问题
- 使用栈计算后缀表达式
- 对栈的元素进行排序
- 判断表达式是否括号平衡
- 括号匹配算法
- Tip借助栈进行数组倒置