python - Python中集合的pop()的时间复杂度是多少?
问题描述
我知道 pop 列表的最后一个元素需要 O(1)。读完这篇文章后
我注意到,如果我们从列表中弹出任意数字需要 O(n),因为所有指针都需要向上移动一个位置。
但是对于集合,没有顺序也没有索引。所以我不确定集合中是否还有指针?
如果不是,set 的 pop() 会是 O(1) 吗?
谢谢。
解决方案
在现代 CPython 实现中,pop
需要分摊的常量时间(我将进一步解释)。在 Python 2 上,它通常是相同的,但在某些情况下性能会严重下降。
Pythonset
基于哈希表,pop
必须在表中找到一个被占用的条目才能删除并返回。如果它每次都从表的开头进行搜索,这将花费与空前导条目的数量成正比的时间,并且每次pop
.
为了避免这种情况,标准的 CPython 实现尝试记住最后一个pop
ped 条目的位置,以加快pop
s 的序列。CPython 3.5+ 在 set 内存布局中有一个专门的finger
成员来存储这个位置,但是早期版本滥用第一个哈希表条目的哈希字段来存储这个索引。
在任何 Python 版本中,使用一系列pop
操作从集合中删除所有元素所花费的时间与底层哈希表的大小成正比,这通常在原始元素数量的一个小的常数因子内(除非你已经删除了一堆元素)。如果插入的元素落在哈希表索引 0 中,则混合插入pop
会严重干扰 Python 2,从而破坏搜索手指。这在 Python 3 上不是什么大问题。
推荐阅读
- node.js - Okta Jwt-Verifier 不工作 - “jwt_verifier_1.OktaJwtVerifier 不是构造函数”
- java - 如何将字符串更改为对象
- python - 如何将字典附加到另一个字典中?
- javascript - 如何删除数组中的匹配元素?
- c - 一旦 3x3 井字棋棋盘中的每一行和每一列都充满了 X 和 O,如何结束循环?
- hbase - Bigtable 列族时间范围扫描返回所有行而不考虑时间戳
- java - ListView 列表 - 引用变量或对象?
- java - Java NewIO:通用复制方法(文件夹到文件夹、zip 到文件夹、文件夹到 zip 等)可能吗?
- css -
- 宽度和文本大小调整
- azure-functions - 如何基于自定义逻辑大规模进行事件中心事件路由