第2章:序列构成的数组-数组 array 和 队列 deque

虽然列表既灵活又简单,但面对各类需求时,我们可能会有更好的选择,比如:

1. 要存放 1000 万个浮点数的话,数组(array)的效率要高得多,因为数组在背后存的并不是 float 对象,而是数字的机器翻译,也就是字节表述。
2. 如果需要频繁对序列做“先进先出”的操作,队列(deque)的速度应该会更快。

2.9.1 数组

如果我们需要一个只包含数字的列表,那么 array.array 比 list 更高效。数组支持所有跟可变序列有关的操作,包括 .pop.insert 和 .extend。另外,数组还提供从文件读取和存入文件的更快的方法,如 .frombytes 和 .tofile

 创建数组需要两个参数,第一个参数是类型码,用来表示在底层C语言中应该存放怎样的数据类型,比如 b 代表的是有符号字符,因此 array('b', ...) 创建的数组只能存放 1 个字节大小的整数,范围是 -128-127; Python 不允许你在数组中存放除指定数据类型外的数据;

示例 一个浮点型数组的创建、存入文件和从文件读取的过程

from array import array
from random import random

# 创建一个包含了100万个随机双精度浮点数的数组
floats = array('d', (random() for _ in range(10**7)))
fp = open('floats.bin', 'wb')
# tofile 将数组存放到二进制文件中
floats.tofile(fp)  

# 新建一个双精度浮点空数组
floats_2 = array('d', [])
fp = open('floats.bin', 'rb')
# fromfile 从指定文件读取数组,第二个参数指定读取的数量
floats_2.fromfile(fp, 10**6)  # 从二进制文件中读取出 100万个浮点数

print(floats == floats_2)  # True

表2-2:列表和数组的属性和方法(不包含过期的数组方法以及那些由对象实现的方法)

 

列表

数组

 

s.__add__(s2)__

s + s2,拼接

s.__iadd__(s2)__

s += s2,就地拼接

s.append(e)

在尾部添加一个元素

s.byteswap

 

翻转数组内每个元素的字节序列,转换字节序

s.clear()

 

删除所有元素

s.__contains__(e)

s 是否含有 e

s.copy()

 

对列表浅复制

s.__copy__()

 

对 copy.copy 的支持

s.count(e)

s 中 e 出现的次数

s.__deepcopy__()

 

对 copy.deepcopy 的支持

s.__delitem__(p)

删除位置 p 的元素

s.extend(it)

将可迭代对象 it 里的元素添加到尾部

s.frombytes(b)

 

将压缩成机器值的字节序列读出来添加到尾部

s.fromfile(f, n)

 

将二进制文件 f 内含有机器值读出来添加到尾部,最多添加 n 项

s.fromlist(l)

 

将列表里的元素添加到尾部,如果其中任何一个元素导致了 TypeError 异常,那么所有的添加都会取消

s.__getitem__(p)

s[p],读取位置 p 的元素

s.index(e)

找到 e 在序列中第一次出现的位置

s.insert(p, e)

在位于 p 的元素之前插入元素 e

s.itemsize

 

数组中每个元素的长度是几个字节

s.__iter__()

返回迭代器

s.__len__()

len(s),序列的长度

s.__mul__(n)

s * n,重复拼接

s.__imul__(n)

s *= n,就地重复拼接

s.__rmul__(n)

n * s,反向重复拼接*

s.pop([p])

删除位于 p 的值并返回这个值,p 的默认值是最后一个元素的位置

s.remove(e)

删除序列里第一次出现的 e 元素

s.reverse()

就地调转序列中元素的位置

s.__reversed__()

 

返回一个从尾部开始扫描元素的迭代器

s.__setitem__(p, e)

s[p] = e,把位于 p 位置的元素替换成 e

s.sort([key], [revers])

 

就地排序序列,可选参数有 key 和 reverse

s.tobytes()

 

把所有元素的机器值用 bytes 对象的形式返回

s.tofile(f)

 

把所有元素以机器值的形式写入一个文件

s.tolist()

 

把数组转换成列表,列表里的元素类型是数字对象

s.typecode

 

返回只有一个字符的字符串,代表数组元素在 C 语言中的类型

2.9.2 双向队列和其他形式的队列 

        利用 .append 和 .pop 方法,我们可以把列表当作栈或者队列来用(比如,把 .append 和 .pop(0) 合起来用,就能模拟队列的“先进先出”的特点)。但是删除列表的第一个元素(抑或是在第一个元素之前添加一个元素)之类的操作是很耗时的,因为这些操作会牵扯到移动列表里的所有元素。

    collections.deque 类(双向队列)是一个线程安全、可以快速从两端添加或者删除元素的数据类型。而且如果想要有一种数据类型来存放“最近用到的几个元素”,deque 也是一个很好的选择。这是因为在新建一个双向队列的时候,你可以指定这个队列的大小,如果这个队列满员了,还可以从反向端删除过期的元素,然后在尾端添加新的元素。

示例 2-23 使用双向队列

from collections import deque

# 创建个新的队列,第一个参数是队列的内容,应该是个可迭代对象,maxlen 参数是指定队列大小
dq = deque(range(10), maxlen=10)
print(dq)  # deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)

# 当参数 n>0 时,将最右侧 n 个元素移动到队列左边,默认 n=1;
dq.rotate(3)  
print(dq)  # deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
# 当 n<0 时,将最左侧 n 个元素移动到右边,默认 n=1;
dq.rotate(-3)
print(dq)  # deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)

# 当队列满了之后,在尾部添加元素的时候,会将头部的元素删掉
dq.append(10)  
print(dq)  # deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10)

# 当队列满了之后,在头添加元素的时候,会将尾部的元素删掉
dq.appendleft(0) 
print(dq)  # deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)

# extend 方法同 append,不过添加的是可迭代对象
dq.extend([...])
dq.extendleft([...])

表2-3:列表和双向队列的方法(不包括由对象实现的方法)

 

列表

双向队列

 

s.__add__(s2)

 

s + s2,拼接

s.__iadd__(s2)

s += s2,就地拼接

s.append(e)

添加一个元素到最右侧(到最后一个元素之后)

s.appendleft(e)

 

添加一个元素到最左侧(到第一个元素之前)

s.clear()

删除所有元素

s.__contains__(e)

 

s 是否含有 e

s.copy()

 

对列表浅复制

s.__copy__()

 

对 copy.copy(浅复制)的支持

s.count(e)

s 中 e 出现的次数

s.__delitem__(p)

把位置 p 的元素移除

s.extend(i)

将可迭代对象 i 中的元素添加到尾部

s.extendleft(i)

 

将可迭代对象 i 中的元素添加到头部

s.__getitem__(p)

s[p],读取位置 p 的元素

s.index(e)

 

找到 e 在序列中第一次出现的位置

s.insert(p, e)

 

在位于 p 的元素之前插入元素 e

s.__iter__()

返回迭代器

s.__len__()

len(s),序列的长度

s.__mul__(n)

 

s * n,重复拼接

s.__imul__(n)

 

s *= n,就地重复拼接

s.__rmul__(n)

 

n * s,反向重复拼接*

s.pop()

移除最后一个元素并返回它的值#

s.popleft()

 

移除第一个元素并返回它的值

s.remove(e)

移除序列里第一次出现的 e 元素

s.reverse()

调转序列中元素的位置

s.__reversed__()

返回一个从尾部开始扫描元素的迭代器

s.rotate(n)

 

把 n 个元素从队列的一端移到另一端

s.__setitem__(p, e)

s[p] = e,把位于 p 位置的元素替换成 e

s.sort([key], [reverse])

 

就地排序序列,可选参数有 key 和 reverse

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArrayDeque是Java中的一个双端队列实现类。它实现了Deque接口,可以将其作为双端队列使用。ArrayDeque还实现了Cloneable接口,可以通过调用clone()方法进行克隆操作。此外,ArrayDeque还实现了java.io.Serializable接口,支持序列化,可以通过序列化进行传输。需要注意的是,ArrayDeque是非同步的,不适用于多线程环境。\[2\] ArrayDeque提供了一系列方法来操作队列,其中包括addLast(E e)方法,用于在队列的末尾添加元素。该方法会将元素e放置在tail位置,并根据需要进行容量扩展。如果添加元素后tail+1等于head,表示内存不足,会调用doubleCapacity()方法将ArrayDeque的容量扩展为原来的两倍。\[3\] 需要注意的是,ArrayDeque的clone()方法会创建一个新的ArrayDeque对象,并将原始队列的元素复制到新的队列中。这是通过调用父类Object的clone()方法实现的,然后使用Arrays.copyOf()方法对元素数组进行深度复制。\[1\] 参考资料: \[1\] ArrayDeque源码 \[2\] ArrayDeque的特性 \[3\] ArrayDeque的addLast()方法实现 #### 引用[.reference_title] - *1* *2* *3* [集合框架之ArrayDeque类详解](https://blog.csdn.net/lucklycoder/article/details/115381856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值