Python中列表的调整大小是多少?

问题描述 投票:4回答:2

例如,Java中的ArrayLists的调整大小因子为2.当ArrayList缠绕的数组空间不足时,该数组的所有元素都将传输到一个大小为原始数组大小2倍的新数组。

由于Python列表/数组自然是动态的,它们的调整大小因素是什么?或者他们使用其他一些缩放方法?如果是这样,那个方法是什么?什么是渐近运行时(大O)?

python python-3.x list data-structures asymptotic-complexity
2个回答
5
投票

特别是对于CPython,调整大小期间的过度分配是在objects/listobject.c中实现的。它被描述为

温和,但......足以在存在性能不佳的系统realloc()的情况下在长序列的appends()上给出线性时间摊销行为。

当需要增长列表时,它增长到大约112.5%的必要大小。特别是,实际大小是new_size + new_size >> 3 + (newsize < 9 ? 3 : 6)


0
投票

要回答你的另一个问题:在ArrayList或类似的末尾添加一个项目需要摊销O(1)时间,只要有任何因子k> 1,这样重新分配总是会产生一个比前一个大k倍的数组。一。

只要它大于一个,所使用的实际因素并不重要。替代的重新分配方案可能具有不同的复杂性。例如,如果重新分配添加了一个常量,那么添加一个项目需要摊销O(N)时间。

这就是为什么所有专业编写的动态增长阵列每次都会增长一些因素。该因子提供了浪费空间比例((k-1)/ k)的固定上限,与每个项目在一系列添加中复制的平均次数的固定上限进行交易。

假设您使用因子k并且您刚刚执行了第N次重新分配。这意味着你已经添加了大约k ^ N个项目。你复制了多少件物品?让我们成为C.然后:

C = k ^(N-1)+ k(N-2)+ ... + 1

kC - C = k ^ N + k ^(N-1) - k ^(N-1)+ k ^(N-2) - k ^(N-2)... - 1

kC - C = k ^ N - 1

C =(k ^ N-1)/(k-1)

每个项目添加的份数,则为C / K ^ N,几乎是1 /(k-1)。

因此,Java的因子k = 2意味着每个添加操作大约有一个副本,最多50%未使用的插槽,而CPython的因子k = 1.125意味着每个添加操作大约有8个副本,最多11%未使用的插槽。

© www.soinside.com 2019 - 2024. All rights reserved.