为什么max比sort更慢?

时间:2016-01-26 13:30:14

标签: python sorting max python-internals

我发现max比Python 2和3中的sort函数慢。

Python 2

$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 239 usec per loop
$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'max(a)'        
1000 loops, best of 3: 342 usec per loop

Python 3

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 252 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a)'
1000 loops, best of 3: 371 usec per loop

为什么 maxO(n))慢于sort函数(O(nlogn))?

3 个答案:

答案 0 :(得分:124)

在Python中使用timeit模块时必须非常小心。

python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'

此处初始化代码运行一次以生成随机数组a。然后其余代码运行几次。它第一次对数组进行排序,但是每隔一段时间就在已排序的数组上调用sort方法。只返回最快的时间,因此您实际上计算了Python对已经排序的数组进行排序所需的时间。

Python的排序算法的一部分是检测阵列何时已经部分或完全排序。完全排序后,它只需扫描一次数组就可以检测到它,然后停止。

如果您尝试了:

python -m timeit -s 'import random;a=range(100000);random.shuffle(a)' 'sorted(a)[-1]'

然后在每个定时循环上进行排序,您可以看到排序数组的时间确实比找到最大值的时间长得多。

编辑: @ skyking的answer解释了我无法解释的部分:a.sort()知道它正在处理列表,因此可以直接访问这些元素。 max(a)适用于任意迭代,因此必须使用泛型迭代。

答案 1 :(得分:88)

首先,注意max() uses the iterator protocol,而list.sort() uses ad-hoc code。显然,使用迭代器是一个重要的开销,这就是为什么你要观察时间差异的原因。

然而,除此之外,您的测试不公平。您在同一列表中多次运行a.sort()algorithm used by Python专门针对已经(部分)排序的数据快速设计。您的测试表明该算法正在很好地完成其工作。

这些都是公平的测试:

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a[:])'
1000 loops, best of 3: 227 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a[:].sort()'
100 loops, best of 3: 2.28 msec per loop

这里我每次都会创建一份列表副本。如您所见,结果的数量级是不同的:微米与毫秒,正如我们所期望的那样。

请记住:大哦指定上限! Python排序算法的下限是Ω( n )。成为O( n log n )并不会自动暗示每次运行都需要与 n log n 成比例的时间。它甚至不意味着它需要比O( n )算法慢,但这是另一个故事。重要的是要理解,在一些有利的情况下,O( n log n )算法可以在O( n )时间内运行或更少

答案 2 :(得分:31)

这可能是因为l.sortlist的成员,而max是通用函数。这意味着l.sort可以依赖list的内部表示,而max必须通过通用迭代器协议。

这使得l.sort的每个元素获取速度都比max的每个元素获取速度快。

我认为如果你使用sorted(a),你会得到比max(a)慢的结果。