01-deque类-双端队列-完全解读

1  deque类的适用场景

1.1 适用场景

deque并非列表的完美替代,一般情况下,它最适用于:

1.1  左入右出,或者 ,右入左出的数据结构。

       只通过对其两端数据的操作,实现压入和弹出。比如:简单的堆栈

1.2  创建有限长度的数据集,对近期有限事务或类似数据池的追踪记录。比如:日志等

1.2  不适合的场景

频繁访问序列中间元素的事务。(通过deque对象存取中间数据的效率相对低,在这种情况下,应当使用列表)

2  简要介绍及deque的发音

collections模块是对python通用容器类型(字典、集合、元组、列表)的补充。

deque对象是其中之一,实现了【双端队列数据类型】及其操作。

发音:deck,即:“double-ended queue”


本文基于官方文档,加入了理解,添加了一些应用实例。

感觉用【双端】更准确,而不是【双向】

3  定义

class collections.deque([iterable[, maxlen]])

对定义的说明:

1、使用deque(),将返回一个新的deque对象;

2、该对象初始化时,使用了append()函数,因此对象中的元素由左自右排列;

3、初始化该对象,使用的数据,来源于参数表中的可迭代对象(iterable);

4、如果未传入可迭代对象(即未传入iterable参数),则该deque对象为空(empty)。


deque对象兼具堆栈和列表的特性:

1、线程安全

2、从两端弹出和添加元素具有极好的运行效能,时间复杂度均为O(1)

3、类比一般列表,在右侧操作效率会非常高,但在左侧或者中间执行类似操作时,效率会大幅降低。

注意:这些特性实质决定了它的应用场景。

4  maxlen参数【重要】

4.1  初始化deque对象时,如果【未指定maxlen或者maxlen的值为None】,则不会限制deque对象中数据项的个数。

4.2  指定的maxlen就是deque对象的最大数据项个数。

【以下特性重要】

4.3  一旦限定长度已满,当添加新的数据项时,将从另一端丢弃相应数量的数据项(有界的deque对象,类似Unix中的尾部过滤器)。

4.4  这种特性,常被用作跟踪和记录最近的事务(就像日志等)。 

备注:maxlen同时也是deque对象中的一个只读属性。

5  deque中的方法

5.1  append(x)

功能:【在右侧】添加数据项

与列表中的append相比,使用方法完全一致。

差异:若deque初始化,传入maxlen参数,则限制了它的长度。再在右侧添加若干元素,就会挤出左侧对应数量的数据项。而列表则不会。

类似的情况,在deque中,向两端添加数据项的操作(比如,appendleft/extend等,均存在,以下不再说明。(使用insert(i,x),超出长度限制时,不会溢出,而是触发异常。)

示例:

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
d.append(6)
print(*d)  # 1 2 3 4 6

ls = [0, 1, 2, 3, 4]
print(*ls)  # 0 1 2 3 4
ls.append(6)
print(*ls)  # 0 1 2 3 4 6

5.2  appendleft(x)

功能:【在左侧】添加数据项

注意:右侧可能挤出

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
d.appendleft(6)
print(*d)  # 6 0 1 2 3

5.3  clear()

功能:清空deque中的所有数据项,将其长度变为0

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
d.clear()
print(len(d))  # 0

5.4  copy()

功能:创建对象的浅拷贝

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
e = d.copy()
print(*e)  # 0 1 2 3 4

5.5  count(x)

功能:返回对象数据项中包含x的数量(跟列表一样)

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
print(d.count(4)) # 1


ls = [0, 1, 2, 3, 4]
print(*ls)  # 0 1 2 3 4
print(ls.count(4))

5.6  extend(iterable)

功能:将传入的可迭代对象,以【单个数据项】的形式,添加到到deque对象右侧。

注意:左侧挤出

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d)  # 0 1 2 3 4
d.extend([7, 8, 9])
print(*d)  # 3 4 7 8 9

这里需要特别注意,extend方法与append方法的区别

extend:以单个元素的形式,添加【可迭代对象】。

append:以整体形式,添加【合法的任意数据项】。

示例如下:

from collections import deque

d1 = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d1)  # 0 1 2 3 4
d1.extend([7, 8, 9])
print(*d1)  # 3 4 7 8 9

d2 = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d2)  # 0 1 2 3 4
d2.append([7, 8, 9])
print(*d2)  # 1 2 3 4 [7, 8, 9]

5.7  extendleft(iterable)

功能:与extend相同,只是方向变为左侧。

注意:添加的顺序与可迭代对象中的元素顺序相反

考虑堆栈,后入先出

示例如下:

from collections import deque

d1 = deque([0, 1, 2, 3, 4], maxlen=5)
print(*d1)  # 0 1 2 3 4
d1.extendleft([7, 8, 9])
print(*d1)  # 9 8 7 0 1

5.8  index(x[, start[, stop]])

功能:在切片[start:end]范围内,返回第一个x的位置,如果未找到,则抛出ValueError异常。

因此,使用index方法,在不确定是否能找到时,需要处理异常,否则程序无法运行。

此方法与列表等序列中的同名方法一致。

示例如下:

from collections import deque

d = deque([0, 1, 2, 3, 4, 5, 3, 4, 5], maxlen=10)
print(*d)  # 0 1 2 3 4 5 3 4 5

ind1 = d.index(3,4) # 从第4个位置(包含)开始找
print(ind1) # 6

ind1 = d.index(3,4,5) 
# 这个语句编译时报错:ValueError: 3 is not in deque

5.9  insert(ix)

功能:在位置i,插入数据项x

注意:与append/extend/extendleft不同的是,插入数据超出maxlen限制时,程序不会从左侧挤出对应数量的数据项,而会抛出IndexError。

示例如下:

from collections import deque

d = deque([0, 1, 2, 3, 4], maxlen=6)
print(*d)  # 0 1 2 3 4
ins = d.insert(1,7)
print(*d) # 0 7 1 2 3 4

ins = d.insert(1,9)
# IndexError: deque already at its maximum size

5.10  pop()

功能:从右侧,弹出并返回数据项,如果没有数据,则抛出IndexError

from collections import deque

d = deque([0, 1], maxlen=6)
print(*d)  # 0 1

pop_num = d.pop()
print(pop_num,*d)  # 1 0

pop_num = d.pop()
print(pop_num,*d)  # 0,此时d中已无数据

d.pop()
# IndexError: pop from an empty deque

5.11  popleft()

功能:与pop()相同,仅将方向变为左侧

5.12  remove(value)

功能:删除遇到的第一个value数据项【注意:这里没有start,stop参数】

from collections import deque

d = deque([0, 1,2,3,4], maxlen=6)
print(*d)  # 0 1 2 3 4
d.remove(4)
print(*d) # 0 1 2 3

5.13  reverse()

功能:反转对象中的各数据项,并返回None【注意,是原地反转,是改变对象自己的数据项】

from collections import deque

d = deque([0, 1,2,3,4], maxlen=6)
print(*d)  # 0 1 2 3 4
d.reverse()
print(*d) # 4 3 2 1 0

5.14  rotate(n=1)

功能:旋转对象中的n个数据项,返回None


            当n为正数时,从右到左(相当于逆时间)旋转n个数据项。

           【为1时,相当于d.appendleft(d.pop())】


            当n为负数时,从左到右(相当于顺时间)旋转n个数据项。

           【为-1时,相当于d.append(d.popleft())】


           当n为0时,数据项不变

示例(n为正时):

from collections import deque

d = deque([0, 1,2,3,4], maxlen=6)
print(*d)  # 0 1 2 3 4
d.rotate(1)
print(*d) # 4 0 1 2 3
d.rotate(2)
print(*d) # 2 3 4 0 1

示例(n为负时):

from collections import deque

d = deque([0, 1,2,3,4], maxlen=6)
print(*d)  # 0 1 2 3 4
d.rotate(-1)
print(*d) # 1 2 3 4 0
d.rotate(-2)
print(*d) # 3 4 0 1 2

5.15 deque支持的其它操作

这些操作不在deque类中实现,而是本身参与表达式运算(如:迭代、二进制封装、成员运算符in、切片操作等),或者将实例作为参数,传给其它函数。

比如:len(d), reversed(d), copy.copy(d), copy.deepcopy(d)

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值