mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
1571 字
8 分钟
python算法学习之列队与双端列队
2026-01-17

一、队列的基本概念#

队列(Queue) 是一种先进先出(FIFO - First In First Out) 的线性数据结构。 队列的核心操作:

  1. 入队(Enqueue):添加元素到队尾
  2. 出队(Dequeue):移除队首元素
  3. 查看队首(Front/Peek):查看但不移除队首元素
  4. 判断空(isEmpty):检查队列是否为空
  5. 获取大小(Size):获取队列中元素数量

队列就像排队买票:

  • 新来的人排在队尾(入队)
  • 买完票的人从队首离开(出队)
  • 先来的人先服务(先进先出)

二、列队的两种视角#

  1. 数组实现(顺序队列) 前端(front) ← [元素1, 元素2, 元素3] ← 后端(rear) 出队← ←入队

  2. 链表实现(链式队列) front → 节点1 → 节点2 → 节点3 → rear

三、队列的实现方式#

  1. 基于数组的实现(顺序队列)

    class ArrayQueue:
    """基于数组的循环队列实现"""
    def __init__(self, capacity=10):
    self.capacity = capacity
    self.queue = [None] * capacity
    self.front = 0 # 队首指针
    self.rear = 0 # 队尾指针(指向下一个空位置)
    self.size = 0 # 当前元素数量
    def __str__(self):
    if self.is_empty():
    return "Queue: []"
    elements = []
    for i in range(self.size):
    idx = (self.front + i) % self.capacity
    elements.append(str(self.queue[idx]))
    return f"Queue: [{', '.join(elements)}] (front:{self.front}, rear:{self.rear})"
    def is_empty(self):
    return self.size == 0
    def is_full(self):
    return self.size == self.capacity
    def enqueue(self, value):
    """入队 - O(1)"""
    if self.is_full():
    self._resize()
    self.queue[self.rear] = value
    self.rear = (self.rear + 1) % self.capacity # 循环
    self.size += 1
    def dequeue(self):
    """出队 - O(1)"""
    if self.is_empty():
    raise IndexError("Dequeue from empty queue")
    value = self.queue[self.front]
    self.queue[self.front] = None # 可选:帮助垃圾回收
    self.front = (self.front + 1) % self.capacity # 循环
    self.size -= 1
    return value
    def peek(self):
    """查看队首元素 - O(1)"""
    if self.is_empty():
    raise IndexError("Peek from empty queue")
    return self.queue[self.front]
    def get_size(self):
    return self.size
    def _resize(self):
    """动态扩容 - O(n)"""
    self.capacity *= 2
    new_queue = [None] * self.capacity
    # 复制元素到新数组,保持顺序
    for i in range(self.size):
    old_idx = (self.front + i) % (self.capacity // 2)
    new_queue[i] = self.queue[old_idx]
    self.queue = new_queue
    self.front = 0
    self.rear = self.size

    测试循环队列

    queue = ArrayQueue(3)
    queue.enqueue(1)
    queue.enqueue(2)
    queue.enqueue(3)
    print(queue) # Queue: [1, 2, 3]
    print("队首:", queue.peek()) # 1
    print("出队:", queue.dequeue()) # 1
    queue.enqueue(4)
    print(queue) # Queue: [2, 3, 4]
  2. 基于链表的实现(链式队列)

    class Node:
    """链表节点"""
    def __init__(self, value):
    self.value = value
    self.next = None
    class LinkedListQueue:
    """基于链表的队列实现"""
    def __init__(self):
    self.front = None # 队首节点
    self.rear = None # 队尾节点
    self._size = 0
    def __str__(self):
    values = []
    current = self.front
    while current:
    values.append(str(current.value))
    current = current.next
    return " → ".join(values) + " → None" if values else "Empty Queue"
    def is_empty(self):
    return self.front is None
    def enqueue(self, value):
    """入队 - O(1)"""
    new_node = Node(value)
    if self.is_empty():
    self.front = self.rear = new_node
    else:
    self.rear.next = new_node
    self.rear = new_node
    self._size += 1
    def dequeue(self):
    """出队 - O(1)"""
    if self.is_empty():
    raise IndexError("Dequeue from empty queue")
    value = self.front.value
    self.front = self.front.next
    # 如果队列变空,更新rear
    if self.front is None:
    self.rear = None
    self._size -= 1
    return value
    def peek(self):
    """查看队首 - O(1)"""
    if self.is_empty():
    raise IndexError("Peek from empty queue")
    return self.front.value
    def size(self):
    return self._size

    测试链表队列

    ll_queue = LinkedListQueue()
    ll_queue.enqueue(1)
    ll_queue.enqueue(2)
    ll_queue.enqueue(3)
    print("链表队列:", ll_queue) # 1 → 2 → 3 → None
    print("队首:", ll_queue.peek()) # 1
    print("出队:", ll_queue.dequeue()) # 1
    print("链表队列:", ll_queue) # 2 → 3 → None

四、双端队列(Deque)#

双端队列(Deque - Double Ended Queue) 是一种允许从两端进行插入和删除操作的数据结构。 双端队列的核心操作:

  1. 前端操作:add_front / remove_front / peek_front
  2. 后端操作:add_rear / remove_rear / peek_rear
  3. 可以同时当作栈和队列使用

双端队列就像双向通道:

  • 可以从两端进入
  • 可以从两端离开
  • 更灵活的数据结构

五、双端队列的实现#

class ArrayDeque:
"""基于数组的双端队列实现(循环数组)"""
def __init__(self, capacity=10):
self.capacity = capacity
self.deque = [None] * capacity
self.front = 0 # 指向队首元素
self.rear = 0 # 指向队尾的下一个位置
self.size = 0
def __str__(self):
if self.is_empty():
return "Deque: []"
elements = []
for i in range(self.size):
idx = (self.front + i) % self.capacity
elements.append(str(self.deque[idx]))
return f"Deque: [{', '.join(elements)}]"
def is_empty(self):
return self.size == 0
def is_full(self):
return self.size == self.capacity
def _resize(self):
"""动态扩容"""
self.capacity *= 2
new_deque = [None] * self.capacity
for i in range(self.size):
old_idx = (self.front + i) % (self.capacity // 2)
new_deque[i] = self.deque[old_idx]
self.deque = new_deque
self.front = 0
self.rear = self.size
def add_front(self, value):
"""前端添加 - O(1)"""
if self.is_full():
self._resize()
self.front = (self.front - 1) % self.capacity
self.deque[self.front] = value
self.size += 1
def add_rear(self, value):
"""后端添加 - O(1)"""
if self.is_full():
self._resize()
self.deque[self.rear] = value
self.rear = (self.rear + 1) % self.capacity
self.size += 1
def remove_front(self):
"""前端移除 - O(1)"""
if self.is_empty():
raise IndexError("Remove from empty deque")
value = self.deque[self.front]
self.deque[self.front] = None
self.front = (self.front + 1) % self.capacity
self.size -= 1
return value
def remove_rear(self):
"""后端移除 - O(1)"""
if self.is_empty():
raise IndexError("Remove from empty deque")
self.rear = (self.rear - 1) % self.capacity
value = self.deque[self.rear]
self.deque[self.rear] = None
self.size -= 1
return value
def peek_front(self):
"""查看前端 - O(1)"""
if self.is_empty():
raise IndexError("Peek from empty deque")
return self.deque[self.front]
def peek_rear(self):
"""查看后端 - O(1)"""
if self.is_empty():
raise IndexError("Peek from empty deque")
return self.deque[(self.rear - 1) % self.capacity]
def size(self):
return self.size

测试双端队列

deque = ArrayDeque(5)
deque.add_rear(1) # 后端添加
deque.add_rear(2)
deque.add_front(0) # 前端添加
deque.add_rear(3)
print(deque) # Deque: [0, 1, 2, 3]
print("前端:", deque.peek_front()) # 0
print("后端:", deque.peek_rear()) # 3
print("移除前端:", deque.remove_front()) # 0
print("移除后端:", deque.remove_rear()) # 3
print(deque) # Deque: [1, 2]

六、对比#

alt text

七、队列的经典应用场景(打印队列管理)#

class PrinterQueue:
"""打印机队列模拟"""
def __init__(self):
self.queue = deque()
self.current_job = None
def add_print_job(self, document, pages, priority="normal"):
"""添加打印任务"""
job = {
'document': document,
'pages': pages,
'priority': priority,
'status': 'waiting'
}
# 根据优先级插入
if priority == "high":
# 插入到普通任务前面
temp_queue = deque()
inserted = False
while self.queue:
job_in_queue = self.queue.popleft()
if not inserted and job_in_queue['priority'] == "normal":
temp_queue.append(job)
inserted = True
temp_queue.append(job_in_queue)
if not inserted:
temp_queue.append(job)
self.queue = temp_queue
else:
self.queue.append(job)
print(f"添加打印任务: {document} ({pages}页)")
def process_next_job(self):
"""处理下一个任务"""
if not self.queue:
print("没有待处理的任务")
return None
self.current_job = self.queue.popleft()
self.current_job['status'] = 'printing'
print(f"正在打印: {self.current_job['document']}")
return self.current_job
def cancel_job(self, document):
"""取消指定任务"""
for job in list(self.queue):
if job['document'] == document:
self.queue.remove(job)
print(f"已取消任务: {document}")
return True
print(f"未找到任务: {document}")
return False
def show_queue(self):
"""显示当前队列"""
print("\n当前打印队列:")
for i, job in enumerate(self.queue, 1):
print(f"{i}. {job['document']} ({job['pages']}页) - {job['priority']}优先级")

总之#

队列思维:先进先出,公平排队 适用场景:需要按顺序处理、先来后到

关键点:

  1. 队尾入,队首出
  2. 保持顺序不变
  3. 常用于缓冲、调度

双端队列思维:两头都能操作,灵活多变 适用场景:需要从两端操作、滑动窗口、同时需要栈和队列功能

关键点:

  1. 两端都可以插入删除
  2. 可以模拟栈和队列
  3. 常用于维护单调性

这里有点难,应该在LeetCode上多练习.

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

python算法学习之列队与双端列队
https://tclothes.online/posts/算法3/sf3/
作者
衣服修改
发布于
2026-01-17
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时