上一篇
双端队列(Deque)是一种具有队列和栈性质的数据结构,支持在两端高效添加和移除元素。Python的collections
模块提供了deque
实现,它是线程安全的,且针对快速插入和删除进行了优化。
什么是双端队列?
双端队列(Deque,全名double-ended queue)是一种允许在队列的前端(front)和后端(rear)进行插入和删除操作的线性数据结构。
A
B
C
D
E
创建双端队列
使用collections.deque
创建双端队列:
from collections import deque
# 创建空双端队列
d = deque()
# 从可迭代对象创建双端队列
d = deque(['apple', 'banana', 'cherry'])
# 指定最大长度(可选)
d = deque(maxlen=5) # 最多容纳5个元素
基本操作方法
双端队列支持在两端高效添加和删除元素:
方法 | 描述 | 时间复杂度 |
---|---|---|
append(x) |
在右端添加元素x | O(1) |
appendleft(x) |
在左端添加元素x | O(1) |
pop() |
移除并返回右端元素 | O(1) |
popleft() |
移除并返回左端元素 | O(1) |
extend(iterable) |
在右端扩展多个元素 | O(k) |
extendleft(iterable) |
在左端扩展多个元素 | O(k) |
rotate(n) |
向右旋转n步(负值向左) | O(k) |
clear() |
清空队列 | O(n) |
使用示例
from collections import deque
# 创建双端队列
d = deque(['b', 'c', 'd'])
print(d) # deque(['b', 'c', 'd'])
# 添加元素
d.append('e') # 右端添加
d.appendleft('a') # 左端添加
print(d) # deque(['a', 'b', 'c', 'd', 'e'])
# 移除元素
right = d.pop() # 移除右端元素
left = d.popleft() # 移除左端元素
print(f"Removed: {left}, {right}") # Removed: a, e
print(d) # deque(['b', 'c', 'd'])
# 旋转操作
d.rotate(1) # 向右旋转1步
print(d) # deque(['d', 'b', 'c'])
d.rotate(-2) # 向左旋转2步
print(d) # deque(['c', 'd', 'b'])
实际应用场景
1
实现队列和栈
使用双端队列可以轻松实现标准队列(FIFO)和栈(LIFO)结构:
# 队列实现 (FIFO)
queue = deque()
queue.append('a') # 入队
queue.append('b')
item = queue.popleft() # 出队
print(item) # 'a'
# 栈实现 (LIFO)
stack = deque()
stack.append('a') # 压栈
stack.append('b')
item = stack.pop() # 出栈
print(item) # 'b'
2
滑动窗口算法
双端队列在解决滑动窗口最大值问题中非常高效:
def max_sliding_window(nums, k):
if not nums:
return []
result = []
dq = deque() # 存储索引
for i in range(len(nums)):
# 移除超出窗口范围的索引
if dq and dq[0] == i - k:
dq.popleft()
# 移除小于当前元素的索引
while dq and nums[dq[-1]] < nums[i]:
dq.pop()
dq.append(i)
# 当窗口形成时记录最大值
if i >= k - 1:
result.append(nums[dq[0]])
return result
# 示例
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
print(max_sliding_window(nums, k)) # [3, 3, 5, 5, 6, 7]
3
回文检查
双端队列是检查字符串是否为回文的理想工具:
def is_palindrome(s):
dq = deque(s.lower().replace(' ', ''))
while len(dq) > 1:
if dq.popleft() != dq.pop():
return False
return True
# 示例
print(is_palindrome("A man a plan a canal Panama")) # True
print(is_palindrome("Python")) # False
deque vs list 性能对比
在队列操作中,deque
比Python列表(list
)性能更高:
操作 | deque | list | 性能差异 |
---|---|---|---|
appendleft/popleft | O(1) | O(n) | deque显著更快 |
append/pop | O(1) | O(1) | 相当 |
随机访问 | O(n) | O(1) | 列表更快 |
中间插入/删除 | O(n) | O(n) | 相当 |
结论
Python的collections.deque
是处理双端队列操作的理想选择。当需要频繁在序列两端添加或删除元素时,deque
提供了比列表更优的性能。
关键点总结:
- 使用
deque
实现队列(FIFO)和栈(LIFO) - 在滑动窗口算法中高效维护窗口
- 线程安全,适合多线程环境
- 指定
maxlen
参数创建有限长度队列 - 避免使用
deque
进行随机访问和中间操作
发表评论