Python sorted()内置函数与list insert()方法的效率

时间:2013-02-13 19:17:53

标签: python performance algorithm

我并不陌生,但我并没有太多使用Python,而且我的知识相当广泛而且语言也不是很深,也许这里知识渊博的人可以回答我的问题。当我需要将项目添加到列表并将其按照添加的项目进行排序时,我发现自己处于这种情况。快速做到这一点的方法是。

list.append(item)                  // O(1)
list.sort()                        // ??

我想如果这是项目添加到列表的唯一方式,我希望排序相当有效,因为列表是按每次添加进行排序的。然而,这也有效:

inserted = False
for i in range(len(list)):         // O(N)
    if (item < list[i]): 
        list.insert(i, item)       // ??
        inserted = True
        break
if not inserted: list.append(item)

有谁可以告诉我,其中一个显然更有效率?我倾向于第二组陈述,但我真的不知道。

2 个答案:

答案 0 :(得分:6)

您正在寻找的是bisect模块,最有可能的是insort_left

所以你的表达式可以等同地写成

some_list.append(item)                  // O(1)
some_list.sort()                        // ??

bisect.insort_left(some_list, item)

答案 1 :(得分:2)

除了接近结尾处的任何地方插入需要O(n)时间,因为它必须移动(复制)插入点之后的所有元素。但另一方面,所有基于比较的排序算法平均必须进行Omega(n log n)比较。许多类型(包括Python使用的timsort)在许多输入上都会做得更好,可能包括你的(“几乎排序”的情况)。他们仍然必须移动至少尽可能多的元素插入正确的位置。他们还需要完成相当多的额外工作(检查所有元素以确保它们的顺序正确,加上更复杂的逻辑,通常可以提高性能,但不是在你的情况下)。由于这些原因,它可能更慢,至少对于大型列表而言。

由于用C语言编写(在CPython中;但类似的推理适用于其他Pythons),它可能仍然比Python编写的线性扫描更快。这留下了如何找到插入点的问题。二进制搜索可以在O(log n)时间内完成这一部分,所以它在这里非常有用(当然,插入仍然是O(n),但是如果你想要一个排序列表,就没办法解决这个问题)。不幸的是,二进制搜索实现起来相当棘手。幸运的是,它已经在标准库中实现:bisect

相关问题