栈(Stack)
栈(Stack)数据结构
栈是一种后进先出(LIFO, Last In First Out)的线性数据结构
类似于进电梯,先进后出(进电梯后别站在最边上哈,不然就先出了,哈哈~)
或者类似洗完,先洗好的放下面,后洗好的放上面,拿碗的时候要拿后洗好的。
核心特性
- LIFO原则:最后入栈的元素最先出栈
- 受限访问:只能从栈顶(top)进行插入和删除操作(只能一端进出,队列就是双端进出,一端进,一端出)
- 基本操作:
push(压栈/入栈):在栈顶添加元素pop(弹栈/出栈):移除并返回栈顶元素peek/top(查看栈顶):返回栈顶元素但不移除isEmpty:检查栈是否为空size:获取栈中元素数量
栈的实现方式
1. 基于数组的实现
public class ArrayStack {
private final int[] stackArray;
private int top;
private final int capacity;
public ArrayStack(int size) {
stackArray = new int[size];
capacity = size;
top = -1;
}
public void push(int item) {
if (isFull()) {
throw new RuntimeException("Stack is full");
}
stackArray[++top] = item;
}
public int pop() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return stackArray[top--];
}
public int peek() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return stackArray[top];
}
public boolean isEmpty() {
return top == -1;
}
public boolean isFull() {
return top == capacity - 1;
}
public int size() {
return top + 1;
}
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(5);
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.pop()); // 输出: 3
System.out.println(stack.peek()); // 输出: 2
System.out.println(stack.size()); // 输出: 2
}
}
2. 基于链表的实现
public class LinkedListStack {
private static class Node {
int data;
Node next;
Node(int data) {
this.data = data;
}
}
private Node top;
private int size;
public void push(int data) {
Node newNode = new Node(data);
newNode.next = top;
top = newNode;
size++;
}
public int pop() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
int data = top.data;
top = top.next;
size--;
return data;
}
public int peek() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty");
}
return top.data;
}
public boolean isEmpty() {
return size == 0;
}
public static void main(String[] args) {
LinkedListStack stack = new LinkedListStack();
stack.push(10);
stack.push(20);
stack.push(30);
System.out.println(stack.pop()); // 输出: 30
System.out.println(stack.peek()); // 输出: 20
}
}
时间复杂度
| 操作 | 数组实现时间复杂度 | 链表实现时间复杂度 | 说明 |
|---|---|---|---|
| push() | O(1) | O(1) | 数组实现:直接 arr[++top] = 插入节点 链表实现:新的节点置为头结点,下一个节点是原来的头结点 |
| pop() | O(1) | O(1) | 数组实现:可以直接返回 arr[top--](仅维护下标,元素其实还在) 链表实现:返回头结点,然后把下一个节点置为头结点 |
| peek() | O(1) | O(1) | 数组时间:直接访问 arr[top](下标不用维护) 链表实现:直接访问头节点 |
| size() | O(1) | O(1) | 数组实现:top+1(下标+1就是有效数据个数) 链表实现:直接访问 size 属性 |
| empty() | O(1) | O(1) | 数组实现:top是否等于-1(判断下标,从0开始,如果小于0就表明是空) 链表实现:头结点是否为空或size是否是0 |
JDK 中的栈
Stack 继承 Vector 数组实现,线程安全(所有方法都使用 synchronized 来同步)
ArrayDeque 数组实现,线程不安全,既具有栈的特性也具有队列的特性

浙公网安备 33010602011771号