Python中的collections模块提供了一种双边队列(deque)的数据结构,它可以在两端进行插入和删除操作,具有比列表更快的操作速度。本文将详细介绍Python collections.deque双边队列的原理和使用方法。
deque(双边队列)的原理
deque(双边队列)是一种具有栈和队列性质的数据结构,因此可以在其中同时进行插入、删除等操作。与列表相比,deque具有如下特点:
- deque可以从队列任意一端插入元素。
- deque可以从队列任意一端删除元素。
- deque具有O(1)的时间复杂度进行插入和删除操作。
deque可以通过以下方式进行创建:
from collections import deque
d = deque()
创建空的deque对象后,我们就可以向其内部插入和删除元素。deque中内置了许多方法,例如append、appendleft、pop、popleft等方法,可以方便地操作deque。
下面我们来分别介绍这些方法:
append和appendleft方法
通过append方法,可以向deque的右侧插入一个元素,而通过appendleft方法,可以向deque的左侧插入一个元素。例如:
from collections import deque
d = deque()
d.append(1) # 右侧插入1,返回None
d.appendleft(2) # 左侧插入2,返回None
print(d) # deque([2, 1])
pop和popleft方法
通过pop方法,可以从deque的右侧弹出一个元素,而通过popleft方法,可以从deque的左侧弹出一个元素。例如:
from collections import deque
d = deque([1, 2, 3])
d.pop() # 弹出3
d.popleft() # 弹出1
print(d) # deque([2])
其他方法
deque内置了许多其他方法,例如rotate、remove等方法,可以方便地进行元素旋转、元素删除等操作。例如:
from collections import deque
d = deque([1, 2, 3])
d.rotate(1) # 右侧旋转一位,返回None
d.remove(2) # 删除元素2,返回None
print(d) # deque([3, 1])
实际应用示例
示例1:使用deque实现窗口大小固定的滑动窗口
deque可以用于实现窗口大小固定的滑动窗口,可以通过左侧弹出和右侧插入的方法实现。例如,我们有一个长度为n的整数数组,给定窗口大小k,在该整数数组中找到所有长度为k的滑动窗口的最大值。代码如下:
from collections import deque
def sliding_window(nums, k):
n = len(nums)
if n < k or k <= 0:
return []
res = []
q = deque()
for i in range(n):
# 当队列非空且当前元素大于队列末尾元素时,删除队列末尾元素
while len(q) > 0 and nums[q[-1]] < nums[i]:
q.pop()
q.append(i)
# 当队列中队头元素已经不在滑动窗口内时,删除队头元素
while q[0] < i + 1 - k:
q.popleft()
# 当队列中元素个数等于窗口大小时,将队头元素作为滑动窗口最大值
if i + 1 >= k:
res.append(nums[q[0]])
return res
print(sliding_window([1, 3, -1, -3, 5, 3, 6, 7], 3)) # [3, 3, 5, 5, 6, 7]
上面的代码中,我们通过双端队列来保存滑动窗口中的元素。队列中保存的是元素下标,而不是元素本身,这样可以避免出现重复元素的情况。
示例2:使用deque实现二叉树的层次遍历
deque可以用于实现二叉树的层次遍历,可以通过左侧插入和右侧插入的方法实现。例如,我们有一个二叉树,需要进行层次遍历。代码如下:
from collections import deque
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def level_order(root):
res = []
if not root:
return res
q = deque([root])
while q:
level = []
size = len(q)
for _ in range(size):
node = q.popleft()
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
res.append(level)
return res
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(level_order(root)) # [[3], [9, 20], [15, 7]]
上面的代码中,我们通过双端队列来保存每一层的节点。先将根节点加入队列,然后循环遍历队列,弹出队列中的节点,并保存其值。将弹出的节点的左右子节点加入队列中,直到队列为空为止。每一层的节点保存在一个列表中,最终将列表保存在结果中。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python collections.deque双边队列原理详解 - Python技术站