Descobri que max
é mais lento do que a sort
função em Python 2 e 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 que é max
( O(n)
) mais lento do que o sort
function ( O(nlogn)
)?
python
sorting
max
python-internals
WeizhongTu
fonte
fonte
a.sort()
funciona no local. Tentesorted(a)
sort
classifica ea
é classificado para sempreRespostas:
Você deve ter muito cuidado ao usar o
timeit
módulo em Python.Aqui, o código de inicialização é executado uma vez para produzir uma matriz aleatória
a
. Em seguida, o resto do código é executado várias vezes. Na primeira vez, ele classifica a matriz, mas a cada duas vezes você chama o método de classificação em uma matriz já classificada. Apenas o tempo mais rápido é retornado, então você está realmente cronometrando quanto tempo leva para o Python classificar um array já classificado.Parte do algoritmo de classificação do Python é detectar quando o array já está parcial ou completamente classificado. Quando completamente classificado, ele simplesmente tem que fazer uma varredura no array para detectar isso e então para.
Se em vez disso você tentou:
então a classificação acontece em cada loop de tempo e você pode ver que o tempo para classificar uma matriz é de fato muito mais longo do que apenas encontrar o valor máximo.
Edit: a resposta de @ skyking explica a parte que deixei sem explicação:
a.sort()
sabe que está trabalhando em uma lista, então pode acessar diretamente os elementos.max(a)
funciona em qualquer iterável arbitrário, portanto, precisa usar a iteração genérica.fonte
a.sort()
sabe que está trabalhando em uma lista, então pode acessar diretamente os elementos.max(a)
funciona em uma sequência arbitrária para não usar iteração genérica.listsort.txt
explica "Ele tem desempenho sobrenatural em muitos tipos de arrays parcialmente ordenados (menos de lg (N!) Comparações necessárias e tão poucas quanto N-1)" e então continua explicando todos os tipos de otimizações sangrentas. Suponho que ele pode fazer muitas suposições quemax
não podem, ou seja, a classificação não é assintoticamente mais rápida.Em primeiro lugar, observe que
max()
usa o protocolo iterador , enquantolist.sort()
usa código ad-hoc . Claramente, usar um iterador é uma sobrecarga importante, é por isso que você está observando essa diferença nos tempos.No entanto, além disso, seus testes não são justos. Você está concorrendo
a.sort()
na mesma lista mais de uma vez. O algoritmo usado pelo Python é projetado especificamente para ser rápido para dados já (parcialmente) classificados. Seus testes estão dizendo que o algoritmo está fazendo seu trabalho bem.Estes são testes controlados:
Aqui estou sempre criando uma cópia da lista. Como você pode ver, a ordem de magnitude dos resultados é diferente: microssegundos vs milissegundos, como seria de se esperar.
E lembre-se: big-Oh especifica um limite superior! O limite inferior para o algoritmo de classificação do Python é Ω ( n ). Ser O ( n log n ) não implica automaticamente que cada execução leva um tempo proporcional a n log n . Nem mesmo implica que precisa ser mais lento do que um algoritmo O ( n ), mas isso é outra história. O que é importante entender é que, em alguns casos favoráveis, um algoritmo O ( n log n ) pode ser executado em tempo O ( n ) ou menos.
fonte
Isto poderia ser porque
l.sort
é um membro dalist
enquantomax
é uma função genérica. Isso significa quel.sort
pode contar com a representação interna delist
whilemax
terá que passar por protocolo iterador genérico.Isso faz com que a busca de cada elemento
l.sort
seja mais rápida do que a busca de cada elementomax
.Presumo que, se você usar
sorted(a)
, obterá o resultado mais lento do quemax(a)
.fonte
sorted(a)
é mais lento do quemax(a)
. Não é de surpreender que seja quase a mesma velocidade quea.sort()
, mas sua conjectura quanto ao motivo pelo qual não é - é porque o OP cometeu um erro em seus testes, conforme apontado na resposta aceita.log(n)
fator de complexidade. Ou seja, umO(n)
algoritmo só tem garantia de ser mais rápido do que umO(nlogn)
algoritmo suficientemente granden
(por exemplo, porque o tempo para cada operação pode ser diferente entre os algoritmos - asnlogn
etapas rápidas podem ser mais rápidas do que asn
lentas). Exatamente onde o ponto de equilíbrio é não considerado neste caso (mas deve-se estar ciente de que olog n
fator não é um fator muito grande para algo pequenon
).