Python 标准库 collections 提供了 deque 类型, 两端均可以操作, 相当于双端队列
对比列表
- list
list 在内部以动态数组实现, 创建时需要预先分配额外空间, 以索引的方式访问元素的时间复杂度为 O(1), 但是在列表中间插入或删除元素时需要移动元素, 时间复杂度为 O(n)
当然, 如果每次都在末尾新增(append)或删除元素(pop), 也可以获得 O(1) 的插入和删除性能
- deque
deque 的底层使用双向链表, 创建时不需要预留空间, 在中间插入或删除元素时不需要移动元素, 不能快速随机访问中间的元素
操作
新建双端队列
deque([iterable[, maxlen]])
不指定 maxlen 或 maxlen 为 None 时, 不限制 deque 的长度
如果指定了最大长度 maxlen, 一旦 deque 的元素数量达到最大长度, 再次从一端新增元素时, deque 会自动在另一端弹出元素
>>> from collections import deque
>>> d1 = deque()
>>> d1
deque([])
>>> d2 = deque('123')
>>> d2
deque(['1', '2', '3'])
>>> d3 = deque('1', maxlen=1)
>>> d3
deque(['1'], maxlen=1)
>>> d3.append('2')
>>> d3
deque(['2'], maxlen=1)
入队以及出队
- 从队尾(右端)入队或出队
d.append(x)
d.extend(iterable)
d.pop()
队列为空时抛出IndexError
>>> d = deque('12')
>>> d
deque(['1', '2'])
>>> d.append('3')
>>> d
deque(['1', '2', '3'])
>>> d.extend('45')
>>> d
deque(['1', '2', '3', '4', '5'])
>>> d.pop()
'5'
>>> d
deque(['1', '2', '3', '4'])
- 从队首(左端)入队或出队
d.appendleft(x)
d.extendleft(iterable)
d.popleft()
队列为空时抛出IndexError
>>> d = deque('12')
>>> d
deque(['1', '2'])
>>> d.appendleft('3')
>>> d
deque(['3', '1', '2'])
>>> d.extendleft('45')
>>> d
deque(['5', '4', '3', '1', '2'])
>>> d.popleft()
'5'
>>> d
deque(['4', '3', '1', '2'])
类似于列表的操作
deque 也属于序列类型, 有许多操作与列表类似
>>> from collections.abc import Sequence
>>> issubclass(deque, Sequence)
True
- 长度
len(d)
双端队列中元素的个数
- 算术运算
类似于列表:
+
连接两个双端队列*
所有元素重复
>>> d_1 = deque('12')
>>> d_2 = deque('3')
>>> d_1 + d_2
deque(['1', '2', '3'])
>>> d_1 * 2
deque(['1', '2', '1', '2'])
- 索引取值和赋值
deque 索引访问两端元素的时间复杂度为 O(1), 访问中间元素的时间复杂度为 O(n) (底层需要遍历链表)
>>> d = deque([1, 2, 3])
>>> d[1]
2
>>> d[-1]
3
>>> d[1] = 0
>>> d
deque([1, 0, 3])
索引对应的元素不存在时报错
- 插入 删除 清空 拷贝 逆序
类似于列表的方法
d.insert(i, x)
插入元素, 注意 deque 已经达到最大长度时再插入会报错)d.remove(value)
删除元素, 存在多个 value 时删除索引最小的那个值, 没有该值时抛出ValueError
d.clear()
清空D = d.copy
浅拷贝d.reverse()
逆序(修改 deque 本身)
>>> d = deque([1, 2], maxlen=4)
>>>
>>> d.insert(0, 0)
>>> d
deque([0, 1, 2], maxlen=4)
>>> d.insert(-1, 3)
>>> d
deque([0, 1, 3, 2], maxlen=4)
# deque 已满
>>> d.insert(1, 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: deque already at its maximum size
>>> d.remove(3)
>>> d
deque([0, 1, 2], maxlen=4)
>>> d.reverse()
>>> d
deque([2, 1, 0], maxlen=4)
>>> d.clear()
>>> d
deque([], maxlen=4)
- 索引与计数
index(x[, start[, stop]])
返回第一次出现的索引, 没有该值时抛出ValueError
count(x)
返回该值出现的次数
>>> d = deque([1, 2, 2, 3, 4])
>>> d.index(2)
1
>>> d.count(2)
2
特有操作
rotate(n=1)
循环右移(修改 deque 本身)
>>> d = deque('ABCD')
>>> d
deque(['A', 'B', 'C', 'D'])
>>> d.rotate(1)
>>> d
deque(['D', 'A', 'B', 'C'])
>>> d.rotate(2)
>>> d
deque(['B', 'C', 'D', 'A'])