Qual é o algoritmo de classificação mais rápido para uma matriz de números inteiros?

55

Eu encontrei muitos algoritmos de classificação durante meus estudos no ensino médio. No entanto, nunca sei qual é o mais rápido (para uma matriz aleatória de números inteiros). Então, minhas perguntas são:

  • Qual é o algoritmo de classificação mais rápido atualmente conhecido?
  • Teoricamente, é possível que existam ainda mais rápidos? Então, qual é a menor complexidade para classificar?
gen
fonte
7
O que você quer dizer com "rápido"? O que você quer medir?
Raphael
2
O que significa "matriz aleatória de números inteiros"? Aleatório com que distribuição? distribuição uniforme? Gaussiano? Dependendo da distribuição, pode haver melhores do que O(nregistron) algoritmos de tempo de execução esperados.
Bakuriu 02/12/2013
@gen Dê uma olhada no Radix sort. A implementação correta possui complexidade O (n) para Int32, por exemplo.
este
Ter um olhar para o ponto de referência tipo
Adriann
11
@gen: Em termos de asymptotics? Então, é fácil: escolha qualquer um dos algoritmos Θ ( n log n ) . Observe que isso pode não ter nada a ver com o desempenho (médio) do mundo real. Esta pode ser uma leitura interessante a esse respeito. ΘΘ(nregistron)
Raphael

Respostas:

42

Em termos gerais, existem os algoritmos de classificação , como classificação de inserção, classificação de bolhas e classificação, que você normalmente deve usar apenas em circunstâncias especiais; Quicksort, que é o pior caso O ( n 2 ), mas muitas vezes O ( n log n ) com boas constantes e propriedades e que pode ser usado como um procedimento de classificação de uso geral; os algoritmos O ( n log n ) , como merge-sort e heap-sort, que também são bons algoritmos de classificação de uso geral; e o O ( nO(n2)O(n2)O(nregistron)O(nregistron) ou algoritmos de classificação lineares para listas de números inteiros, como classificação de raiz, intervalo e contagem, que podem ser adequados, dependendo da natureza dos números inteiros nas suas listas.O(n)

Se os elementos em sua lista são tais que tudo que você sabe sobre eles é o relacionamento total de pedidos entre eles, os algoritmos de classificação ideais terão complexidade . Esse é um resultado bastante interessante e sobre o qual você poderá encontrar facilmente detalhes on-line. Os algoritmos de classificação linear exploram informações adicionais sobre a estrutura dos elementos a serem classificados, em vez de apenas o relacionamento total da ordem entre os elementos.Ω(nregistron)

De maneira ainda mais geral, a otimização de um algoritmo de classificação depende intimamente das suposições que você pode fazer sobre o tipo de lista que você classificará (bem como o modelo de máquina em que o algoritmo será executado, o que pode tornar a classificação ainda mais ruim) algoritmos a melhor escolha; considere a classificação de bolhas em máquinas com uma fita para armazenamento). Quanto mais fortes forem as suas suposições, mais chances o seu algoritmo poderá cortar. Sob suposições muito fracas sobre a eficiência com que você pode determinar a "classificação" de uma lista, a complexidade ideal do pior caso pode ser .Ω(n!)

Esta resposta lida apenas com complexidades. O tempo real de execução das implementações de algoritmos dependerá de um grande número de fatores que são difíceis de explicar em uma única resposta.

Patrick87
fonte
Eu acho que alguns daqueles deve ser Ω ? OΩ
Raphael
11
@Raphael Meh. Eu acho que a maioria deles são de qualquer maneira. Suponho que o limite inferior provavelmente seja melhor renderizado Ω . Vou mudar alguns deles que fazem mais sentido. ΘΩ
Patrick87
7
Eu voto @Raphael recebe um polícia chapéu : PΩ
Realz Slaw
2
@RealzSlaw: Eu usaria com orgulho. :]
Raphael
11
@gen Consulte stackoverflow.com/a/3274203 para alguma discussão. Basicamente, se os registros individuais são enormes e não são armazenados de maneira aleatória, e a quantidade de dados é tal que deve ser feita no local, a classificação das bolhas é o caminho a seguir. Hoje em dia essas circunstâncias são raras, mas você ainda pode encontrá-las.
Patrick87
16

A resposta, como costuma ser o caso de tais perguntas, é "depende". Depende de coisas como (a) quão grandes são os números inteiros, (b) se a matriz de entrada contém números inteiros em uma ordem aleatória ou quase ordenada, (c) se você precisa que o algoritmo de classificação seja estável ou não, bem como outros fatores, (d) se a lista inteira de números se encaixa na memória (classificação na memória versus classificação externa) e (e) na máquina em que você a executa.

Na prática, o algoritmo de classificação na biblioteca padrão do seu idioma provavelmente será muito bom (bem próximo do ideal), se você precisar de uma classificação na memória. Portanto, na prática, basta usar qualquer função de classificação fornecida pela biblioteca padrão e medir o tempo de execução. Somente se você achar que (i) a classificação é uma grande fração do tempo de execução geral e (ii) o tempo de execução é inaceitável, você deve se preocupar em mexer no algoritmo de classificação. Se essas duas condições fazem espera, então você pode olhar para os aspectos específicos de seu domínio e experiência particular com outros algoritmos rápido de ordenação.

Mas, realisticamente, na prática, o algoritmo de classificação raramente é um grande gargalo de desempenho.

DW
fonte
9

Além disso, respondendo sua segunda pergunta

Teoricamente, é possível que existam ainda mais rápidos?
Então, qual é a menor complexidade para classificar?

Para classificação de uso geral, a complexidade do problema de classificação baseada em comparação é Ω (n log n) . Existem alguns algoritmos que executam a classificação em O (n), mas todos eles se baseiam em suposições sobre a entrada e não são algoritmos de classificação de uso geral.

Basicamente, a complexidade é dada pelo número mínimo de comparações necessárias para classificar a matriz (log n representa a altura máxima de uma árvore de decisão binária criada ao comparar cada elemento da matriz).

Você pode encontrar a prova formal para classificar o limite inferior da complexidade aqui :

rla4
fonte
3
Esta resposta não está certa. não é um limite inferior universal para classificação. Esse limite inferior se aplica apenas a classificações baseadas em comparação , ou seja, algoritmos de classificação que usam apenas comparações. Alguns algoritmos de classificação não são baseados em comparação. A declaração "Existem alguns algoritmos que executam a classificação em O (n), mas todos eles se baseiam em suposições sobre a entrada e não são algoritmos de classificação de uso geral". pode ser um pouco enganador - tenha cuidado. Radix-sort é um algoritmo de classificação de uso geral (assumindo que você esteja classificando números inteiros de largura fixa). Ω(nregistron)
DW
Depende do que você quer dizer com problema de classificação . As classificações baseadas em comparação de uso geral não são o único tipo de problemas de classificação que as pessoas têm.
Patrick87
11
Isso é verdade, é claro. Eu deveria ter sido mais específico, obrigado por apontar. No entanto, fiquei um pouco curioso sobre quais outras abordagens de classificação (não baseadas em comparação) a que você estava se referindo; Radix Sort é exatamente o tipo de algoritmo O (n) de que eu estava falando - você precisa 'assumir' algo sobre a entrada (números inteiros de largura fixa). Nesse sentido, não é um algoritmo de classificação de uso geral, certo?
precisa
11
@DW: A classificação Radix não deve ser considerada um algoritmo de classificação 'de uso geral', pois requer chaves inteiras de comprimento fixo; não é útil de outra maneira. Mas entendi seu ponto. :) Acho que meu erro foi focar na classificação de qualquer coisa que pudesse ser comparada, em vez de classificar números inteiros , especificamente. São problemas diferentes e têm um conjunto diferente de soluções possíveis. A pergunta menciona "uma matriz aleatória de números inteiros", mas admito que tomei como exemplo, e não como restrição.
precisa saber é
2
@DavidRicherby, olhando para trás depois de um ano e meio, concordo com você. Obrigado.
DW
3

O algoritmo de classificação inteira mais rápido em termos do pior caso que encontrei é o de Andersson et al. Ele tem o pior caso de , que é obviamente mais rápido que O ( n log n ) .O(nloglogn)O(nlogn)

user39994
fonte
2
Isso é muito interessante, mas você precisa fornecer mais informações. Como você menciona , presumo que você esteja ciente de que a classificação baseada em comparação de números inteiros gerais provavelmente requer tempo Ω ( n log n ) . Qualquer coisa assintoticamente mais rápida do que isso tem que fazer suposições sobre os dados: por exemplo, a classificação radix é executada em tempo linear, assumindo que todos os elementos da matriz são no máximo constantes. Sob quais condições esse algoritmo classifica em O ( n log log n ) e como ele atua na prática em relação a outros algoritmos, como quicksort e radix sort? nlognΩ(nlogn)O(nloglogn)
David Richerby
1

Li as outras duas respostas no momento em que escrevi isso e não achei que nenhuma delas respondesse sua pergunta adequadamente. Outras respostas consideraram idéias estranhas sobre distribuições aleatórias e complexidade do espaço que provavelmente estão fora do escopo dos estudos do ensino médio. Então aqui está a minha opinião.

An(n1)A(n1)Ω(n)O(n)Ω(n)

Ω(n)O(n)n2n3n-51 1n2

bourbaki4481472
fonte
O(n)nlgnn232.O(n)O(nlgn)(para quicksort ou mergesort), na prática a comparação não é tão clara: as constantes ocultas na notação big-O tornam-se muito importantes, e a constante para classificação por raiz é maior que a constante para quicksort ou fusão.
DW
"a constante na frente de n é efetivamente escalada como " Na verdade, não entendo o que você quer dizer com essa frase (entendo que a notação Big-Oh esconde constantes que podem ser importantes para n pequeno ). eug(n)n
precisa saber é o seguinte
Ω(n)
2
O argumento de @ DW é que o verdadeiro custo da classificação de raiz é O(Wn)WWW{0 0,...,2W-1 1}registronnW=registronnregistron.
David Richerby
1

O(neuogeuogn)
O(neuogeuogvocê)você
o bobo
fonte
0

registro(n!)

Ω(n)

Yves Daoust
fonte
0

Como você não menciona nenhuma restrição no hardware e, como procura o "mais rápido", eu diria que você deve escolher um dos algoritmos de classificação paralela com base no hardware disponível e no tipo de entrada que você possui.

Em teoria, por exemplo, quick_sorté O(n log n). Com os pprocessadores, o ideal é que isso ocorra O(n/p log n)se o executarmos em paralelo.

Para citar a Wikipedia: Complexidade temporal de ...

A classificação paralela ideal é O (log n)

Na prática, para tamanhos de entrada massivos, seria impossível obter O(log n)devido a problemas de escalabilidade.

Aqui está o pseudo-código para a classificação de mesclagem paralela . A implementação de merge()pode ser a mesma que na classificação de mesclagem normal:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Veja também:

Kashyap
fonte
O Quicksort não é realmente adequado para processamento paralelo na forma padrão, o que significa que qualquer classificador bitônico deve ser melhor em média ou o Quicksort é modificado (mais do que a introdução, onde a fase de mesclagem é dominante) ou as várias fases de divisão são concluídas no ambiente host, que é contraproducente para paralelização. Em teoria, o Quicksort é de fato O(n2)
@Evil Yes. O Quicksort não é adequado para processamento paralelo. É um exemplo Os que devem ser usados ​​estão listados nos links fornecidos.
Kashyap