社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

分析Python的Dict insert运行时间有什么错?

D. Ulick • 3 年前 • 1246 次点击  

根据我对Python源代码的理解,插入dict的工作原理如下:

insert(e)

  1. 允许 j 是已分配数组中的元素数,并且 k 是数组的大小。(与 K 存在 8
  2. 如果 j+1 < 2/3k 插入 e 进入这个位置 hash(e)%k (暂时不要担心碰撞)
  3. 否则,将数组调整为两倍大小的数组。 K 现在是两倍大,这需要 O(k_prev)

对于 n 插入,有 log(n)-3 调整总时间复杂度的大小 O(log(n)) 但所有网上资源似乎都在说,我应该把这次行动看作是 O(1) ?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/133913
 
1246 次点击  
文章 [ 2 ]  |  最新文章 3 年前
ShadowRanger
Reply   •   1 楼
ShadowRanger    3 年前

事实上,重播 O(n) 成本,但考虑到它很少见,而且相对便宜(散列是预先计算和缓存的,并且您知道现有元素都不相等,所以可以假设一个完整的桶不相等),这通常不是什么大问题。

所以不,任何给定的操作实际上可能是 O(n) .但很像 list 扩张,这是 摊销 O(1) O(1) 插入;即使没有重新灰化,也可以进行给定的插入 O(n) 如果您设法确保插入的所有项都以相同的哈希值模化基础存储大小,但Python会将内置类型的哈希值最小化)。

它仍然存在的原因 O(1) 摊销是指每个元素(重新)插入的平均数量仍受一个常数乘数的约束,该乘数在大O术语中是可忽略的。你可能是在平均 O(2) O(3) 每次插入,但因为 数字 再烧一次就好了 向下 大小 (完成的工作)在重新灰烬中,它真正做的只是意味着你正在更频繁地进行插入工作,但这并没有增加 每个元素的平均值 以成本为基础 dict 生长。

Frank Yellin
Reply   •   2 楼
Frank Yellin    3 年前

当他们说 O(1) ,意思是“摊余成本”。有些手术可能更昂贵,但手术的平均成本仍然很低 O(1) .


我最初的答案如下。我意识到我的证明可以大大简化。

假设当前数组大小为 P = 2^n .一些元素 k 已从上一个数组复制到此数组中。每次复制时,我们复制的元素数量是上一次复制时的两倍。所以移动的元素总数是 k + k/2 + k/4 + ... 这比 2k 这比 2P .

如果我们表演过 N 操作时,数组的大小小于 2N ,我们的表现还不到 4N 副本。因此,副本数量为 O(N) .QED

请注意,我从未在证明中使用过2/3。我们唯一需要的是,每个副本的大小是前一个副本的两倍,并且数组大小与操作数成正比。


这是我最初的答案。

让我们假设在数组已满3/4时复制。这个想法还是一样的,但我们可以用整数。我们从大小为8到16的数组中复制6个元素。我们将12个元素复制到大小为32的数组中。我们将24个元素复制到大小为64的数组中。

[我在用 ^ 指指数,而非排他性或

所以我们最终复制了 6(1 + 2 + 4 + ... 2^n) 元素组成一个数组 2^(n + 3) .但第一个数字小于 6 * 2^(n + 1) 这就是 1.5 * 2^(n * 3) 。因此,无论我们当前使用的是什么大小的数组,到达该数组的复制总量都不到该数组大小的1.5倍。