python数组的时间复杂性?
python数组的时间复杂性?,python,numpy,Python,Numpy,array.array和np.array的.append时间复杂度是多少 我在中看到了list、collections.deque、set和dict的时间复杂度,但我找不到array.array和np.array的时间复杂度。在哪里可以找到它们?了解数组数据结构对于回答您的问题很重要。由于这两个array对象都基于C数组(,),因此它们共享许多相同的功能 将项目添加到数组中是摊销的,但在大多数情况下,最终是摊销时间。这是因为您的数组对象可能尚未填充,因此将一些数据附加到内存中的该位置是一个相对简
array.array
和np.array
的.append
时间复杂度是多少
我在中看到了
list
、collections.deque
、set
和dict
的时间复杂度,但我找不到array.array
和np.array
的时间复杂度。在哪里可以找到它们?了解数组
数据结构对于回答您的问题很重要。由于这两个array
对象都基于C数组(,),因此它们共享许多相同的功能
将项目添加到数组中是摊销的,但在大多数情况下,最终是摊销时间。这是因为您的数组对象可能尚未填充,因此将一些数据附加到内存中的该位置是一个相对简单的操作,这就是O(1)
。但是,在大多数情况下,数组已满,因此需要在内存中完全复制,并添加新项。这是一个非常昂贵的操作,因为需要复制n
大小的数组,从而使插入O(n)
为了使这更清楚,考虑因素是<代码> 2 < /代码>的情况。 初始数组大小为
1
。然后考虑复制成本来增长数组。
从大小1到足够容纳的位置,任意尺寸的2^k+1个元素
k>=0
。此大小为2^(k+1)
。总拷贝成本将包括所有
复制要在2次因子步骤中变得如此巨大:
理解
数组
数据结构对于回答您的问题非常重要。由于这两个array
对象都基于C数组(,),因此它们共享许多相同的功能
将项目添加到数组中是摊销的,但在大多数情况下,最终是摊销时间。这是因为您的数组对象可能尚未填充,因此将一些数据附加到内存中的该位置是一个相对简单的操作,这就是O(1)
。但是,在大多数情况下,数组已满,因此需要在内存中完全复制,并添加新项。这是一个非常昂贵的操作,因为需要复制n
大小的数组,从而使插入O(n)
为了使这更清楚,考虑因素是<代码> 2 < /代码>的情况。 初始数组大小为
1
。然后考虑复制成本来增长数组。
从大小1到足够容纳的位置,任意尺寸的2^k+1个元素
k>=0
。此大小为2^(k+1)
。总拷贝成本将包括所有
复制要在2次因子步骤中变得如此巨大:
因此,为了链接您提供的(也是一个TLDR)列表在内部“表示为一个数组”,它应该是O(1),底部有一个注释:
这些操作依赖于“摊余最坏情况”中的“摊余”部分。根据集装箱的历史,单个操作可能需要惊人的长时间
更多详细信息
文档中没有详细介绍,但如果你看一下,你会真正看到发生了什么。Pythonarray
s具有内部缓冲区,允许快速调整自身大小,并且在其增长/收缩时将realloc
array.append
使用which调用操作的主要部分。顺便提一下,array.extend
也使用它,但它只提供了Py_SIZE(self)
作为插入索引
因此,如果我们阅读arraymodule.ins1
中的注释,它从以下内容开始:
This over-allocates proportional to the array size, making room
for additional growth. The over-allocation is mild, but is
enough to give linear-time amortized behavior over a long
sequence of appends() in the presence of a poorly-performing
system realloc().
The growth pattern is: 0, 4, 8, 16, 25, 34, 46, 56, 67, 79, ...
Note, the pattern starts out the same as for lists but then
grows at a smaller rate so that larger arrays only overallocate
by about 1/16th -- this is done because arrays are presumed to be more
memory critical.
因此,为了链接您提供的(也是一个TLDR)列表在内部“表示为一个数组”,它应该是O(1),底部有一个注释:
这些操作依赖于“摊余最坏情况”中的“摊余”部分。根据集装箱的历史,单个操作可能需要惊人的长时间
更多详细信息
文档中没有详细介绍,但如果你看一下,你会真正看到发生了什么。Pythonarray
s具有内部缓冲区,允许快速调整自身大小,并且在其增长/收缩时将realloc
array.append
使用which调用操作的主要部分。顺便提一下,array.extend
也使用它,但它只提供了Py_SIZE(self)
作为插入索引
因此,如果我们阅读arraymodule.ins1
中的注释,它从以下内容开始:
This over-allocates proportional to the array size, making room
for additional growth. The over-allocation is mild, but is
enough to give linear-time amortized behavior over a long
sequence of appends() in the presence of a poorly-performing
system realloc().
The growth pattern is: 0, 4, 8, 16, 25, 34, 46, 56, 67, 79, ...
Note, the pattern starts out the same as for lists but then
grows at a smaller rate so that larger arrays only overallocate
by about 1/16th -- this is done because arrays are presumed to be more
memory critical.
你是说array.array
?对于numpy来说,这绝对是linear@juanpa.arrivillaga是~np.append()
相当慢,它将涉及复制整个arrayList append相对高效,因为它只是将对象的引用添加到列表的“扩展”空间np.append
是np.concatenate
的一个构思糟糕的覆盖函数。它每次都会生成一个全新的数组。最佳实践是在循环中列出append,并在最后只进行一次连接以形成一个数组。array.array
和numpy.ndarray
是完全不同的实现。一个人可以成长,成长的方式与list
差不多。另一个不能ndarray
主要用于高效的多维计算。去年我回答了一个类似的问题——你是说array.array
?对于numpy来说,这绝对是linear@juanpa.arrivillaga是~np.append()
相当慢,它将涉及复制整个arrayList append相对高效,因为它只是将对象的引用添加到列表的“扩展”空间<代码>np.append
是一个构思拙劣的封面游戏
This over-allocates proportional to the array size, making room
for additional growth. The over-allocation is mild, but is
enough to give linear-time amortized behavior over a long
sequence of appends() in the presence of a poorly-performing
system realloc().
The growth pattern is: 0, 4, 8, 16, 25, 34, 46, 56, 67, 79, ...
Note, the pattern starts out the same as for lists but then
grows at a smaller rate so that larger arrays only overallocate
by about 1/16th -- this is done because arrays are presumed to be more
memory critical.