【发布时间】:2010-12-04 01:18:26
【问题描述】:
基于this older thread,看起来Python中列表函数的成本是:
- 随机访问:O(1)
- 在前面插入/删除:O(n)
- 插入/删除到后面:O(1)
谁能确认这在 Python 2.6/3.x 中是否仍然适用?
【问题讨论】:
标签: python performance list
基于this older thread,看起来Python中列表函数的成本是:
谁能确认这在 Python 2.6/3.x 中是否仍然适用?
【问题讨论】:
标签: python performance list
没错,在前面插入会强制所有元素移动到位。
collections.deque 提供类似的功能,但针对两侧插入进行了优化。
【讨论】:
看看here。这是针对不同类型列表的 PEP。指定的版本是 2.6/3.0。
追加(插入到后面)是O(1),而插入(其他任何地方)是O(n)。所以是的,看起来这仍然是真的。
Operation...Complexity
Copy........O(n)
Append......O(1)
Insert......O(n)
Get Item....O(1)
Set Item....O(1)
Del Item....O(n)
Iteration...O(n)
Get Slice...O(k)
Del Slice...O(n)
Set Slice...O(n+k)
Extend......O(k)
Sort........O(n log n)
Multiply....O(nk)
【讨论】:
Python 3 主要是一种进化变化,在数据结构及其复杂性方面没有大的变化。
Python 集合的规范来源是 Wiki 上的 TimeComplexity。
【讨论】:
Fwiw,如果需要,有一个更快的(对于某些操作...插入 O(log n))list implementation,称为 BList。 BList
【讨论】:
我知道这篇文章很旧,但我最近自己做了一个小测试。 list.insert() 的复杂度似乎是 O(n)
代码:
'''
Independent Study, Timing insertion list method in python
'''
import time
def make_list_of_size(n):
ret_list = []
for i in range(n):
ret_list.append(n)
return ret_list
#Estimate overhead of timing loop
def get_overhead(niters):
'''
Returns the time it takes to iterate a for loop niter times
'''
tic = time.time()
for i in range(niters):
pass #Just blindly iterate, niter times
toc = time.time()
overhead = toc-tic
return overhead
def tictoc_midpoint_insertion(list_size_initial, list_size_final, niters,file):
overhead = get_overhead(niters)
list_size = list_size_initial
#insertion_pt = list_size//2 #<------- INSERTION POINT ASSIGMNET LOCATION 1
#insertion_pt = 0 #<--------------- INSERTION POINT ASSIGNMENT LOCATION 4 (insert at beginning)
delta = 100
while list_size <= list_size_final:
#insertion_pt = list_size//2 #<----------- INSERTION POINT ASSIGNMENT LOCATION 2
x = make_list_of_size(list_size)
tic = time.time()
for i in range(niters):
insertion_pt = len(x)//2 #<------------- INSERTION POINT ASSIGNMENT LOCATION 3
#insertion_pt = len(x) #<------------- INSERTION POINT ASSIGN LOC 5 insert at true end
x.insert(insertion_pt,0)
toc = time.time()
cost_per_iter = (toc-tic)/niters #overall time cost per iteration
cost_per_iter_no_overhead = (toc - tic - overhead)/niters #the fraction of time/iteration, #without overhead cost of pure iteration
print("list size = {:d}, cost without overhead = {:f} sec/iter".format(list_size,cost_per_iter_no_overhead))
file.write(str(list_size)+','+str(cost_per_iter_no_overhead)+'\n')
if list_size >= 10*delta:
delta *= 10
list_size += delta
def main():
fname = input()
file = open(fname,'w')
niters = 10000
tictoc_midpoint_insertion(100,10000000,niters,file)
file.close()
main()
查看 5 个可以插入的位置。成本当然取决于列表的大小,以及您与列表开头的距离(即必须重新组织多少内存位置)
忽略情节的左图
【讨论】: