Algoritmos esféricos no vácuo são ótimos. No entanto, vamos descer do céu para a terra pecaminosa e ver como toda essa beleza teórica se provará na prática.
A análise da próxima classe de tipos terminará com testes para as classes. Hoje vamos executar (não no sentido de jogar fora, mas no sentido de executar em testes) trocas de classificação. Outras classes serão executadas mais tarde.
Na corrida de hoje envolvida:
Grupo mais fraco
Esses algoritmos não reivindicam nada devido à complexidade deprimente do tempo. Nós os testamos puramente para referência.

Tipo bobo

Classificação lenta

Classificação muda
É ainda mais interessante não apenas o quão bom eles são, mas o quanto eles são ruins nos negócios e qual deles é o pior.
Grupo principal
Aqui, reunimos trocas de trocas a la O (
n 2 ). Classificação de anões (e sua otimização) + todos os tipos de variações de classificação de bolhas.

Classificação dos Anões

Classificação anã (otimizada)

Classificação da bolha

Classificação de coquetéis

Tipo ímpar
Esta é a parte mais interessante das medidas de hoje. É entre os representantes do grupo principal que se espera a luta mais teimosa.
Grupo mais forte
Uma das variedades da bolha - classificando por um pente - conseguiu superar a barreira O (
n 2 ) e alcançar o O consagrado pelo tempo (
n log n ). Portanto, em nossa competição, a triagem rápida tem um rival digno. Além disso, experimente o
k-sort recém-inventado , que é uma variação da classificação rápida.

Classificar escova de cabelo

Classificação rápida

K classificação
Os mais fortes, a propósito, não são apenas comparáveis entre si. Em alguns conjuntos de dados, o grupo principal estará em concorrência séria.
Código fonte
Classificações do Python Exchangedef stooge_rec(data, i = 0, j = None): if j is None: j = len(data) - 1 if data[j] < data[i]: data[i], data[j] = data[j], data[i] if j - i > 1: t = (j - i + 1) // 3 stooge_rec(data, i, j - t) stooge_rec(data, i + t, j) stooge_rec(data, i, j - t) return data def stooge(data): return stooge_rec(data, 0, len(data) - 1) def slow_rec(data, i, j): if i >= j: return data m = (i + j) // 2 slow_rec(data, i, m) slow_rec(data, m + 1, j) if data[m] > data[j]: data[m], data[j] = data[j], data[m] slow_rec(data, i, j - 1) return data def slow(data): return slow_rec(data, 0, len(data) - 1) def stupid(data): i, size = 1, len(data) while i < size: if data[i - 1] > data[i]: data[i - 1], data[i] = data[i], data[i - 1] i = 1 else: i += 1 return data def gnome(data): i, size = 1, len(data) while i < size: if data[i - 1] <= data[i]: i += 1 else: data[i - 1], data[i] = data[i], data[i - 1] if i > 1: i -= 1 return data def gnome_opt(data): i, j, size = 1, 2, len(data) while i < size: if data[i - 1] <= data[i]: i, j = j, j + 1 else: data[i - 1], data[i] = data[i], data[i - 1] i -= 1 if i == 0: i, j = j, j + 1 return data def bubble(data): changed = True while changed: changed = False for i in range(len(data) - 1): if data[i] > data[i+1]: data[i], data[i+1] = data[i+1], data[i] changed = True return data def shaker(data): up = range(len(data) - 1) while True: for indices in (up, reversed(up)): swapped = False for i in indices: if data[i] > data[i+1]: data[i], data[i+1] = data[i+1], data[i] swapped = True if not swapped: return data def odd_even(data): n = len(data) isSorted = 0 while isSorted == 0: isSorted = 1 for i in range(1, n - 1, 2): if data[i] > data[i + 1]: data[i], data[i + 1] = data[i + 1], data[i] isSorted = 0 for i in range(0, n - 1, 2): if data[i] > data[i + 1]: data[i], data[i + 1] = data[i + 1], data[i] isSorted = 0 return data def comb(data): gap = len(data) swaps = True while gap > 1 or swaps: gap = max(1, int(gap / 1.25))
Classificações do Exchange PHP Tempo
O tempo é medido em qualquer lugar em segundos, com precisão de microssegundos.
Se um pacote de matrizes (de dez, cem ou até um milhão de peças) for alimentado imediatamente para o algoritmo, o tempo total será indicado.
O ferro é meu laptop fiel e velho que conhecia tempos melhores. Então, muito possivelmente, tudo funcionará para você muito mais rápido.
O pior dos piores
Lidar imediatamente com pessoas de fora. Matrizes para 40/50/60 elementos contendo números aleatórios de 0 a 9 são preparados para eles.
| tipo = aleatório, único = Falso, min = 0, máx = 9, contagem = 1 |
---|
tamanho |
---|
40. | 50. | 60 |
---|
Python | Php | Python | Php | Python | Php |
---|
 | 0,004 | 0,001 | 0,005 | 0,003 | 0,007 | 0,004 |
---|
 | 0,007 | 0,009 | 0,018 | 0,009 | 0,018 | 0,023 |
---|
 | 0,02 | 8.26647 | 0,053 | 20,8722 | 0,12901 | 45.9786 |
---|
A classificação estúpida é uma ordem de magnitude mais rápida que a classificação boba, e a classificação boba é uma ordem de magnitude mais rápida que a lenta. Não há mais nada para assistir.
Camponeses médios
Para verificar a média, foram gerados pacotes de cem matrizes de 100 elementos cada (números únicos de 100 a 999), bem como pacotes de dez matrizes de 1000 elementos cada (números exclusivos de 1000 a 9999).
Matrizes aleatórias, matrizes quase ordenadas e matrizes inversas são preparadas.
Peso Médio: Aleatório
| tipo = aleatório, único = Verdadeiro |
---|
tamanho (mínimo a máximo) × contagem |
---|
100 (100 a 999) × 100 | 1000 (1000 a 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,14101 | 0,18901 | 1,59109 | 1.7251 |
---|
 | 0,20601 | 0,22301 | 2.33013 | 2.09712 |
---|
 | 0,15301 | 0,22901 | 1,6711 | 2.23613 |
---|
 | 0,21601 | 0,26402 | 2.55515 | 2,73116 |
---|
 | 0,16701 | 0,33402 | 1.7251 | 3.13218 |
---|
Em torno dos mesmos resultados para todos. As implementações em Python funcionam um pouco mais rápido que o PHP.
Middles: Quase ordenados
| type = quase, único = True |
---|
tamanho (mínimo a máximo) × contagem |
---|
100 (100 a 999) × 100 | 1000 (1000 a 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,009 | 0,005 | 0,009 | 0,005 |
---|
 | 0,009 | 0,014 | 0,01 | 0,014 |
---|
 | 0,01 | 0,01 | 0,011 | 0,008 |
---|
 | 0,011 | 0,008 | 0,013 | 0,008 |
---|
 | 0,011 | 0,017 | 0,013 | 0,017 |
---|
Todos têm os mesmos resultados, mais ou menos. Do interessante: encomendar dados parciais dezenas de vezes melhora o desempenho de todos os algoritmos.
Meio: Reverso
| tipo = reverso, único = Verdadeiro |
---|
tamanho (mínimo a máximo) × contagem |
---|
100 (100 a 999) × 100 | 1000 (1000 a 9999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,26801 | 0,35902 | 3.10018 | 3.4292 |
---|
 | 0,39602 | 0,45303 | 4.49726 | 4.19524 |
---|
 | 0,22701 | 0,38402 | 2,48114 | 3.64421 |
---|
 | 0,30202 | 0,42603 | 3,3419 | 4.17524 |
---|
 | 0,30402 | 0,64404 | 3.36519 | 6.22036 |
---|
Há uma conclusão interessante - a ordem inversa não afeta tanto a velocidade, que caiu apenas 2 vezes em comparação com o número aleatório.
Meio: Binário
| tipo = aleatório, único = Falso, min = 0, max = 1 |
---|
tamanho × contagem |
---|
100 × 100 | 1000 × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,073 | 0,094 | 0,81105 | 0,86905 |
---|
 | 0,10401 | 0,11301 | 1.16307 | 1.06606 |
---|
 | 0,08801 | 0,12901 | 0,86405 | 1,18207 |
---|
 | 0,11501 | 0,15001 | 1,30107 | 1,41608 |
---|
 | 0,11401 | 0,25801 | 1.31908 | 2,44614 |
---|
De mais ou menos interessante: se em vez de números de 100 a 9999 você classificar zeros e um, os indicadores de velocidade não crescerão muito.
Campeões
A principal intriga aqui é se a triagem com um pente e uma triagem k pode espremer o jejum do pedestal?
Campeões: Aleatório
Para descobrir, vamos formar pacotes de matriz aleatória: 10 peças de 10 mil elementos e 10 peças de 100 mil elementos. Eu queria dar milionários aos algoritmos de entrada, mas o laptop não puxou. Como não há RAM suficiente, a profundidade da recursão é muito grande.
| tipo = aleatório, único = Falso, contagem = 10 |
---|
tamanho (mínimo até máximo) |
---|
10000 (de 10000 a 99999) | 100000 (de 100000 a 999999) |
---|
Python | Php | Python | Php |
---|
 | 0,80205 | 0,63104 | 10.4506 | 8.24647 |
---|
 | 0,47703 | 1,64009 | 6.65138 | 26.5435 |
---|
 | 0.90005 | 2.18613 | 15.8089 | 29.4867 |
---|
A classificação do Python K é mais lenta e o PHP é mais rápido que a classificação rápida.
Classificar o pente em comparação com o rápido parece sólido, embora seja inferior a ele em todos os testes (e nestes e nos seguintes) para quaisquer conjuntos de dados.
No entanto, existem pentes e uma importante vantagem indiscutível. Não possui recursão e, portanto, diferentemente de seus colegas, processa com sucesso matrizes de milhões de elementos.
Casos especiais
Embora os campeões sejam centenas de vezes mais rápidos que os camponeses comuns, em alguns conjuntos de dados específicos as classificações mostram mais simplesmente que não são facilmente costuradas.
Casos especiais: quase ordenados
Vamos tentar matrizes quase ordenadas, basta ter um tamanho maior do que as testadas para os camponeses comuns.
Um pacote de 10 matrizes de 10 mil cada e um pacote de 10 matrizes de 100 mil elementos cada.
| type = quase, único = Falso |
---|
tamanho (mínimo a máximo) × contagem |
---|
10000 (de 10000 a 99999) × 10 | 100000 (de 100000 a 999999) × 10 |
---|
Python | Php | Python | Php |
---|
 | 0,43202 | 0,058 | 0,81705 | 0,58003 |
---|
 | 0,084 | 0,062 | 0,85805 | 0,54003 |
---|
 | 0,11601 | 0,12401 | 1.41908 | 1.36008 |
---|
 | 0,14001 | 0.11901 | 1.83411 | 1,41708 |
---|
 | 0,13801 | 0,23101 | 1,6491 | 2.56915 |
---|
 | ? | 122.088 | ? | ? |
---|
 | 0,71504 | 1,58909 | 9.78356 | 19.4731 |
---|
A classificação rápida não está presente aqui - não havia RAM suficiente. Ao mesmo tempo, matrizes aleatórias com 10/100 mil elementos são processadas pelo quicksort com um estrondo. O k-sort teve problemas semelhantes, gerou apenas 10 milésimos em PHP. Matrizes grandes quase classificadas são um caso degenerado para classificação rápida e suas modificações. Devido a esse arranjo de elementos, a recursão divide a matriz em partes para quase todos os pares de elementos adjacentes, o que leva ao número máximo possível de chamadas de recursão.
A propósito, a situação é semelhante com grandes matrizes de ordem inversa. O mesmo problema surge com os quase ordenados - o algoritmo deve se chamar para cada par de elementos adjacentes.
Classificando por um pente, embora funcione uma vez e meia ou duas vezes mais devagar que rápido ou k (em geral), mas não possui os estouros de memória mencionados acima. Sem recursão - não há problema.
Bem, notamos que todos os camponeses do meio alcançaram os campeões em grandes arranjos quase ordenados. Então o princípio funcionou: "Indo silenciosamente - você continuará".
Casos especiais: milhões de rosas escarlates de pequenas matrizes
Pequenas matrizes - o elemento dos camponeses médios. Se você precisar processar um grande número de pequenos conjuntos de números, poderá obter um ganho de tempo adotando uma classificação "primitiva" de bolha ou gnomo. E use a classificação rápida e outras similares para tarefas maiores.
| tipo = aleatório, único = Verdadeiro |
---|
tamanho (mínimo a máximo) × contagem |
---|
5 (10 a 99) × 1.000.000 | 10 (10 a 99) × 1.000.000 |
---|
Python | Php | Python | Php |
---|
 | 11.77267 | 17.888 | 24.29039 | 33.6659 |
---|
 | 12.51872 | 18.165 | 29.33268 | 35,202 |
---|
 | 15.44188 | 17.861 | 30.06672 | 36.7911 |
---|
 | 14.18681 | 19.7831 | 31.65981 | 39,3533 |
---|
 | 13.63978 | 24.3374 | 28.41662 | 52.864 |
---|
 | 14.21881 | 21.1452 | 25,80548 | 32.5419 |
---|
 | 14.58683 | 28.5016 | 24.85942 | 50.3139 |
---|
 | 18.53806 | 30.7238 | 29.6647 | 58.2493 |
---|
Com as trocas, tudo fica claro. Agora, a parte realmente interessante - a classificação por inserções.
Referências
Aplicativo AlgoLab do Excel , com o qual você pode visualizar passo a passo a visualização desses tipos (e não apenas deles).
Todas as matrizes na forma de JSON também são dispostas no
disco do Google .
Wiki -
Parvo / Pateta , Lento , Anão / Gnomo , Bolha / Bolha , Agitador / Agitador , Ímpar / Par , Pente / Pente , Rápido / RápidoArtigos da série