1 概念
一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈
顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。
2 底层继承
如下图所示,Java中的Stack继承于Vctor,但是Vector在Java已经过时了,我们现在用的是栈,他的底层是一个数组,所以由此又可以分为顺序栈和链栈。
3 顺序栈
- 判断栈满
public boolean empty(){
return this.top == 0;
}
- 判断栈空
public boolean isFull(){
return this.elem.length == this.top;
}
- 入栈操作
public void push(int item) {
//1、判断当前栈是否是满的
if(isFull()){
this.elem = Arrays.copyOf(this.elem,2*this.elem.length); //扩容
}
//2、elem[top] = item top++;
this.elem[this.top++] = item;
}
- 出栈操作
public int pop() {
if(empty()) {
throw new UnsupportedOperationException("栈为空!");
}
int ret = this.elem[this.top-1];
this.top--;//真正的改变了top的值
return ret;
}
- 得到栈顶元素,但是不删除
public int peek() {
if(empty()) {
throw new UnsupportedOperationException("栈为空!");
}
//this.top--;//真正的改变了top的值
return this.elem[this.top-1];
}
4 链栈
Q:1.3中的栈是数组实现的,我们称其为顺序栈,那么换个思路,栈能否用链表来实现?
如下图所示,分别是尾插法和头插法进行入栈操作创建的栈。我们分析一下这个过程,尾插法进行入栈操作时,每一次都要找栈顶元素入栈,也就是说需要遍历一次链表,所以时间复杂度为O(N),而头插法直接插到头节点前面即可,无需遍历,所以时间复杂度为O(1),由此得出结论:
采用头插法实现链表栈效率最高;