Descubrí que max
es más lento que la sort
función en Python 2 y 3.
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
¿Por qué es max
( O(n)
) más lenta que la sort
función ( O(nlogn)
)?
python
sorting
max
python-internals
WeizhongTu
fuente
fuente
a.sort()
funciona en el lugar. Pruebasorted(a)
sort
las clases, y luegoa
se ordenan siempreRespuestas:
Debe tener mucho cuidado al usar el
timeit
módulo en Python.Aquí, el código de inicialización se ejecuta una vez para producir una matriz aleatoria
a
. Luego, el resto del código se ejecuta varias veces. La primera vez que ordena la matriz, pero cada dos veces se llama al método sort en una matriz ya ordenada. Solo se devuelve el tiempo más rápido, por lo que en realidad está midiendo cuánto tiempo le toma a Python ordenar una matriz ya ordenada.Parte del algoritmo de clasificación de Python es detectar cuándo la matriz ya está ordenada parcial o completamente. Cuando está completamente ordenado, simplemente tiene que escanear una vez a través de la matriz para detectar esto y luego se detiene.
Si en cambio lo intentaste:
luego, la clasificación ocurre en cada ciclo de tiempo y puede ver que el tiempo para clasificar una matriz es mucho más largo que simplemente encontrar el valor máximo.
Editar: la respuesta de @ skyking explica la parte que dejé sin explicar:
a.sort()
sabe que está trabajando en una lista, por lo que puede acceder directamente a los elementos.max(a)
funciona en cualquier iterable arbitrario, por lo que debe usar una iteración genérica.fuente
a.sort()
sabe que está trabajando en una lista, por lo que puede acceder directamente a los elementos.max(a)
funciona en una secuencia arbitraria para no utilizar iteraciones genéricas.listsort.txt
explica "Tiene un rendimiento sobrenatural en muchos tipos de matrices parcialmente ordenadas (se necesitan menos de lg (N!) Comparaciones y tan pocas como N-1)" y luego explica todo tipo de optimizaciones sangrientas. Supongo que puede hacer muchas suposiciones quemax
no, es decir, la clasificación no es asintóticamente más rápida.En primer lugar, tenga en cuenta que
max()
utiliza el protocolo iterador , mientras quelist.sort()
utiliza código ad-hoc . Claramente, el uso de un iterador es una sobrecarga importante, por eso está observando esa diferencia en los tiempos.Sin embargo, aparte de eso, sus pruebas no son justas. Estás
a.sort()
en la misma lista más de una vez. El algoritmo utilizado por Python está diseñado específicamente para ser rápido para datos ya ordenados (parcialmente). Tus pruebas dicen que el algoritmo está haciendo bien su trabajo.Estas son pruebas justas:
Aquí estoy creando una copia de la lista cada vez. Como puede ver, el orden de magnitud de los resultados es diferente: micro- vs milisegundos, como era de esperar.
Y recuerde: ¡gran-Oh especifica un límite superior! El límite inferior del algoritmo de clasificación de Python es Ω ( n ). Ser O ( n log n ) no implica automáticamente que cada ejecución requiera un tiempo proporcional an log n . Ni siquiera implica que deba ser más lento que un algoritmo O ( n ), pero esa es otra historia. Lo que es importante entender es que en algunos casos favorables, un algoritmo O ( n log n ) puede ejecutarse en O ( n ) tiempo o menos.
fuente
Esto podría deberse a que
l.sort
es miembro delist
whilemax
es una función genérica. Esto significa quel.sort
puede confiar en la representación interna delist
whilemax
tendrá que pasar por un protocolo de iterador genérico.Esto hace que la búsqueda de cada elemento
l.sort
sea más rápida que la búsqueda de cada elementomax
.Supongo que si en su lugar usa
sorted(a)
, obtendrá el resultado más lento quemax(a)
.fuente
sorted(a)
es más lento quemax(a)
. No es sorprendente quea.sort()
tenga aproximadamente la misma velocidad que , pero su conjetura sobre la razón por la que no lo es, es porque el OP cometió un error en sus pruebas como se señala en la respuesta aceptada.log(n)
factor de complejidad. Es decirO(n)
, solo se garantiza que unO(nlogn)
algoritmo sea más rápido que un algoritmo para lo suficientemente granden
(por ejemplo, porque el tiempo de cada operación puede diferir entre los algoritmos;nlogn
los pasos rápidos pueden ser más rápidos quen
los pasos lentos). En este caso, no se consideró exactamente dónde está el punto de equilibrio (pero uno debe tener en cuenta que ellog n
factor no es un factor muy importante para los pequeñosn
).