数据结构里的两种秩序,一个像叠盘子,一个像排队。
👋 你好,我是 Evan,一名计算机专业的学长,也是《大一突围》专栏的作者。学完数组和链表后,下一个该学什么?栈和队列------它们是"受限"的线性表,但正因为限制,它们解决了无数实际问题:函数调用、括号匹配、浏览器回退、任务调度......今天我用最直观的方式,带你彻底搞懂栈和队列的 push/pop 与 enqueue/dequeue。
欢迎来到 《大一突围》 专栏。

一、栈(Stack):后进先出(LIFO)
1.1 形象比喻
一叠盘子:你只能从顶部取(pop),也只在顶部放(push)。最后放上去的盘子,最先被拿走。
1.2 核心操作
-
push(item):将元素压入栈顶 -
pop():移除并返回栈顶元素 -
peek()/top():查看栈顶元素但不移除 -
isEmpty():判断栈是否为空
1.3 栈的图示

1.4 代码实现(Python + Java)
🐍 Python 示例(使用 list)
python
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
if not self.is_empty():
return self.items.pop()
def peek(self):
if not self.is_empty():
return self.items[-1]
def is_empty(self):
return len(self.items) == 0
# 使用
s = Stack()
s.push(1); s.push(2); s.push(3)
print(s.pop()) # 3
print(s.peek()) # 2
☕ Java 示例(使用 Deque)
java
import java.util.ArrayDeque;
import java.util.Deque;
public class StackDemo {
public static void main(String[] args) {
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // 等价于 addFirst
stack.push(2);
stack.push(3);
System.out.println(stack.pop()); // 3
System.out.println(stack.peek()); // 2
}
}
1.5 经典应用场景
-
函数调用栈:调用方法时压栈,返回时出栈。
-
括号匹配 :
{ ( [ ) ] }用栈检查是否配对。 -
撤销操作(Undo):每次操作压栈,撤销时出栈。
-
浏览器后退:访问新页面压栈,后退弹出。
二、队列(Queue):先进先出(FIFO)
2.1 形象比喻
排队买票:先来的先买到,后来的排在队尾。队头出队(dequeue),队尾入队(enqueue)。
2.2 核心操作
-
enqueue(item):将元素加入队尾 -
dequeue():移除并返回队头元素 -
front()/peek():查看队头元素 -
isEmpty():判断队列是否为空
2.3 队列的图示

2.4 代码实现(Python + Java)
🐍 Python 示例(使用 collections.deque)
python
from collections import deque
class Queue:
def __init__(self):
self.items = deque()
def enqueue(self, item):
self.items.append(item) # 队尾入
def dequeue(self):
if not self.is_empty():
return self.items.popleft() # 队头出
def front(self):
if not self.is_empty():
return self.items[0]
def is_empty(self):
return len(self.items) == 0
# 使用
q = Queue()
q.enqueue(1); q.enqueue(2); q.enqueue(3)
print(q.dequeue()) # 1
print(q.front()) # 2
☕ Java 示例(使用 Queue 接口)
java
import java.util.LinkedList;
import java.util.Queue;
public class QueueDemo {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // enqueue
queue.offer(2);
queue.offer(3);
System.out.println(queue.poll()); // dequeue → 1
System.out.println(queue.peek()); // 查看队头 → 2
}
}
2.5 经典应用场景
-
任务调度(打印队列、进程调度)。
-
广度优先搜索(BFS):借助队列逐层遍历图。
-
消息队列(如 RabbitMQ、Kafka 的底层概念)。
-
键盘缓冲区:你敲的字符先进入队列,系统依次处理。
三、栈 vs 队列:对比总结

代码操作对比表

四、进阶:用数组实现一个循环队列
常规队列用数组实现时,队头出队后前面的空间浪费。循环队列可以重用空间。
循环队列示意图

Python 实现(固定大小)
python
class CircularQueue:
def __init__(self, capacity):
self.capacity = capacity
self.queue = [None] * capacity
self.front = 0
self.rear = 0
self.size = 0
def enqueue(self, item):
if self.size == self.capacity:
raise Exception("Queue is full")
self.queue[self.rear] = item
self.rear = (self.rear + 1) % self.capacity
self.size += 1
def dequeue(self):
if self.size == 0:
raise Exception("Queue is empty")
item = self.queue[self.front]
self.front = (self.front + 1) % self.capacity
self.size -= 1
return item
这个实现不仅更节省空间,而且广泛应用于操作系统和底层库。
五、实战练习:用栈实现队列
这是一道经典的面试题:仅使用两个栈实现队列的 enqueue 和 dequeue 操作。
思路:一个栈作为输入栈(用于 enqueue),另一个栈作为输出栈(用于 dequeue)。当需要 dequeue 时,如果输出栈为空,就把输入栈的所有元素弹出并压入输出栈。
python
class QueueUsingTwoStacks:
def __init__(self):
self.in_stack = []
self.out_stack = []
def enqueue(self, item):
self.in_stack.append(item)
def dequeue(self):
if not self.out_stack:
while self.in_stack:
self.out_stack.append(self.in_stack.pop())
if not self.out_stack:
raise Exception("Queue is empty")
return self.out_stack.pop()
# 测试
q = QueueUsingTwoStacks()
q.enqueue(1); q.enqueue(2); q.enqueue(3)
print(q.dequeue()) # 1
print(q.dequeue()) # 2
q.enqueue(4)
print(q.dequeue()) # 3
print(q.dequeue()) # 4
六、Evan 的一句话总结
-
栈:优先照顾"后来者",适合需要回溯、逆向的场景。
-
队列:公平对待"先来者",适合需要顺序、缓存的场景。
掌握这两种数据结构,你就掌握了一半的算法基础。
❓ 问题:你有没有遇到过用栈或队列巧妙地解决某个实际问题的例子?或者你还分不清什么时候用栈、什么时候用队列?欢迎在评论区分享你的理解或困惑,我会选出 3 位同学,送出《栈和队列经典面试题集合》PDF。
📌 如果本文帮你理清了栈与队列的区别,请点 👍 赞 + 关注 ,本专栏 《大一突围》 持续输出数据结构与算法干货。
收藏本文,下次面试前回看,不再混淆 push/pop 和 enqueue/dequeue。