Quando cada algoritmo de classificação é usado? [fechadas]

170

Quais são os casos de uso em que um algoritmo de classificação específico é preferido em relação a outros - classificação por mesclagem vs QuickSort vs heapsort vs 'classificação por introdução', etc?

Existe um guia recomendado para usá-los com base no tamanho, tipo de estrutura de dados, memória e cache disponíveis e desempenho da CPU?

sam
fonte
Um conjunto de animações para diferentes tipos de dados e algoritmos pode ser encontrado em <a href=" sorting-algorithms.com/"> sorting-algorithms.com </ a >
Chip Uni
2
Um guia como o bigocheatsheet.com para esse material seria bom
K - A toxicidade no SO está crescendo.
@ChipUni aqui está o link fixo: toptal.com/developers/sorting-algorithms
eric
2
Por que esta pergunta está fechada !?
Arvand

Respostas:

316

Primeiro, uma definição, uma vez que é muito importante: uma classificação estável é aquela garantida para não reordenar elementos com chaves idênticas.

Recomendações:

Classificação rápida: quando você não precisa de uma classificação estável e o desempenho médio do caso importa mais do que o pior desempenho do caso. Uma classificação rápida é O (N log N) em média, O (N ^ 2) no pior caso. Uma boa implementação usa armazenamento auxiliar O (log N) na forma de espaço de pilha para recursão.

Classificação de mesclagem: quando você precisa de uma classificação O (N log N) estável, trata-se da sua única opção. A única desvantagem disso é que ele usa espaço auxiliar O (N) e tem uma constante um pouco maior que uma ordenação rápida. Existem algumas classificações de mesclagem no local, mas elas não são estáveis ​​ou piores que O (N log N). Até as ordenações O (N log N) existentes têm uma constante muito maior que a ordenação antiga simples, que são mais curiosidades teóricas do que algoritmos úteis.

Classificação de pilha: quando você não precisa de uma classificação estável e se preocupa mais com o desempenho do pior caso do que com o desempenho médio do caso. Ele é garantido como O (N log N) e usa o espaço auxiliar O (1), o que significa que você não ficará inesperadamente sem espaço de pilha nem empilhará espaço em entradas muito grandes.

Introsort: Esta é uma classificação rápida que alterna para uma classificação de pilha após uma certa profundidade de recursão para contornar o pior caso de O (N ^ 2) da classificação rápida. É quase sempre melhor do que uma classificação rápida simples e antiga, já que você obtém o caso médio de uma classificação rápida, com desempenho garantido de O (N log N). Provavelmente, o único motivo para usar uma classificação de heap em vez disso é em sistemas com muita restrição de memória, nos quais o espaço de pilha O (log N) é praticamente significativo.

Classificação de inserção : quando N é garantidamente pequeno, inclusive como o caso base de uma classificação rápida ou de mesclagem. Embora seja O (N ^ 2), ele tem uma constante muito pequena e é um tipo estável.

Classificação por bolha, seleção : quando você está fazendo algo rápido e sujo e, por algum motivo, não pode usar o algoritmo de classificação da biblioteca padrão. A única vantagem que eles têm sobre a classificação por inserção é ser um pouco mais fácil de implementar.


Classificações sem comparação: sob algumas condições bastante limitadas, é possível quebrar a barreira O (N log N) e classificar em O (N). Aqui estão alguns casos em que vale a pena tentar:

Classificação de contagem: quando você classifica números inteiros com um intervalo limitado.

Classificação de raiz: quando log (N) é significativamente maior que K, onde K é o número de dígitos de raiz.

Classificação de intervalo: quando você pode garantir que sua entrada seja distribuída aproximadamente uniformemente.

dsimcha
fonte
1
Pelo que me lembro, a classificação de heap também tem um tempo de execução muito previsível, pois há pouca variação entre diferentes entradas do mesmo tamanho, mas isso é menos interessante do que o espaço constante. Também acho o tipo de inserção o mais fácil de implementar dos tipos n ^ 2, mas talvez seja apenas eu. Finalmente, você também pode mencionar a classificação do Shell, que é quase tão simples de implementar quanto a classificação de inserção, mas tem melhor desempenho, embora ainda não seja n log n.
21338 JaakkoK
29
Não se esqueça do Bogosort ! ;-) #
1179 Alex Brasetvik
2
+1 muito interessante. Gostaria de explicar como você pode "garantir ... aproximadamente uniformemente distribuído". para classificação de balde?
21720 Sam Overton
2
Por que o introsort seria substancialmente mais lento que a classificação rápida? A única sobrecarga é contar a profundidade da recursão, que deve ser insignificante. Ele só muda após a recursão ser muito mais profunda do que deveria ser em um bom caso de classificação rápida.
dsimcha 20/12/2009
2
Você não mencionou que o melhor caso de classificação de bolha é O (n)!
Tara
33

O Quicksort geralmente é o mais rápido, em média, mas possui alguns comportamentos desagradáveis ​​no pior dos casos. Portanto, se você precisar garantir que nenhum dado incorreto seja fornecido O(N^2), evite-o.

Classificação de mesclagem usa memória extra, mas é particularmente adequada para classificação externa (ou seja, arquivos enormes que não cabem na memória).

A classificação de heap pode classificar no local e não tem o pior comportamento quadrático, mas na média é mais lenta que a classificação rápida na maioria dos casos.

Onde apenas números inteiros em um intervalo restrito estão envolvidos, você pode usar algum tipo de classificação de raiz para torná-lo muito rápido.

Em 99% dos casos, você ficará bem com o tipo de biblioteca, que geralmente é baseado no quicksort.

Eli Bendersky
fonte
6
+1: Para "Em 99% dos casos, você ficará bem com as classificações da biblioteca, que geralmente são baseadas no quicksort".
Jim G.
A rotação aleatória fornece ao Quicksort um tempo de execução de O (nlogn) para todos os fins práticos, sem a necessidade de garantias sobre dados incorretos. Realmente não acho que alguém implemente um quicksort O (n ^ 2) para qualquer código de produção.
MAK
2
MAK, exceto, digamos, a biblioteca padrão C qsort? ( Google.com/codesearch/... ) - sobre o qual a maioria dos tipos "código de produção" confiar
Eli Bendersky
Geralmente, a classificação da biblioteca não se baseia no quicksort, porque não é estável. Quase todos os idiomas superiores (esperados para C) oferecem uma classificação estável. Na maioria dos casos, eu sei que você precisa de um tipo estável, ou pelo menos determinístico.
12431234123412341234123
3

O que os links fornecidos para comparações / animações não consideram é quando a quantidade de dados excede a memória disponível - nesse ponto, o número de passagens sobre os dados, isto é, custos de E / S, dominam o tempo de execução. Se você precisar fazer isso, leia sobre "classificação externa", que geralmente cobre variantes de classificações de mesclagem e heap.

http://corte.si/posts/code/visualisingsorting/index.html e http://corte.si/posts/code/timsort/index.html também têm algumas imagens interessantes comparando vários algoritmos de classificação.

Alex Brasetvik
fonte
0

@dsimcha escreveu: Contando classificação: quando você está classificando números inteiros com um intervalo limitado

Eu mudaria isso para:

Classificação de contagem: quando você classifica números inteiros positivos (0 - Inteiro.MAX_VALUE-2 devido ao buraco de pombo).

Você sempre pode obter os valores max e min como uma heurística de eficiência em tempo linear também.
Além disso, você precisa de pelo menos n espaço extra para a matriz intermediária e é estável, obviamente.

/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

(mesmo que isso permita MAX_VALUE-2), consulte: As matrizes Java têm um tamanho máximo?

Também explicaria que a complexidade da classificação de radix é O (wn) para n chaves que são números inteiros do tamanho da palavra w. Às vezes, w é apresentado como uma constante, o que tornaria a classificação de raiz melhor (para n suficientemente grande) do que os melhores algoritmos de classificação com base em comparação, que todos executam comparações O (n log n) para classificar n chaves. No entanto, em geral w não pode ser considerado uma constante: se todas as chaves n forem distintas, então w deve ser pelo menos log n para que uma máquina de acesso aleatório possa armazená-las na memória, o que oferece, na melhor das hipóteses, uma complexidade de tempo O (n log n). (da wikipedia)

Droid Teahouse
fonte