Existem algoritmos de classificação piores que o Bogosort (também conhecido como Monkey Sort)? [fechadas]

178

Meus colegas de trabalho me levaram de volta no tempo aos meus dias na Universidade com uma discussão sobre algoritmos de classificação nesta manhã. Lembramos nossos favoritos como o StupidSort e um de nós tinha certeza de ter visto um algoritmo de classificação O(n!). Isso me levou a procurar os "piores" algoritmos de classificação que pude encontrar.

Postulamos que uma classificação completamente aleatória seria muito ruim (ou seja, randomizar os elementos - está em ordem? Não? Randomizar novamente), e eu olhei em volta e descobri que ela aparentemente se chama BogoSort, ou Monkey Sort, ou às vezes apenas Random Sort .

Monkey Sort parece ter um desempenho de pior caso O(∞), um desempenho de melhor caso O(n)e um desempenho médio de O(n·n!).

Qual é o algoritmo de classificação atualmente aceito oficialmente com o pior desempenho médio de classificação (e, portanto, pior que O(n·n!))?

womp
fonte
10
Quantos bogomips por bogosort? Mentes inquiridoras querem saber.
zombat 9/04
13
Para esclarecer, você está excluindo o caso trivial em que o melhor desempenho do caso é O (∞)?
Tloflin
6
Ouvi dizer que o tipo de macaco também é conhecido como "tipo de homem bêbado", um nome que acho muito mais sugestivo.
Matteo Italia
6
@ Matteo Italia - ou poderia ser chamado de "Classificação Infantil", como qualquer pessoa com 2 anos de idade pode atestar.
Martin Capodici

Respostas:

442

Da página de Algoritmos Esotéricos de David Morgan-Mar : Classificação de Design Inteligente

Introdução

A classificação de design inteligente é um algoritmo de classificação baseado na teoria do design inteligente.

Descrição do algoritmo

A probabilidade da lista de entrada original estar na ordem exata em que está é 1 / (n!). Há uma probabilidade tão pequena disso que é claramente absurdo dizer que isso aconteceu por acaso, então deve ter sido conscientemente colocado nessa ordem por um Classificador inteligente. Portanto, é seguro supor que ele já esteja classificado de maneira ideal de alguma maneira que transcenda nossa ingênua compreensão mortal da "ordem ascendente". Qualquer tentativa de alterar essa ordem para se adequar aos nossos próprios preconceitos na verdade a tornaria menos classificada.

Análise

Esse algoritmo é constante no tempo e classifica a lista no local, sem necessidade de memória adicional. Na verdade, ele nem sequer exige nada disso material tecnológico suspeito. Elogie o classificador!

Comentários

Gary Rogers escreve:

Fazer o tipo constante no tempo nega o poder do Classificador. O Classificador existe fora do tempo, portanto o tipo é atemporal. Exigir tempo para validar a classificação diminui o papel do Classificador. Assim ... esse tipo específico é falho e não pode ser atribuído a 'O Classificador'.

Heresia!

BioGeek
fonte
94
Também conhecido como "Classificação de suposição": suponha que a lista esteja classificada, retorne!
precisa saber é
42
+100 - esta resposta é feita de 100% de vitória pura.
Womp 09/04
11
Ei! Não se esqueça de "Classificação indecisa" (também conhecida como "Classificação de Schrodinger" ou "Classificação quântica"), em que a lista pode ou não ser classificada. No entanto, a verificação revelará se é ou não. Aqui está minha implementação de exemplo: void quantum_sort (void *b, size_t n, size_t s, int (*c)(const void *, const void*)) { if (rand () % 2) qsort (b, n, s, c); }.
Joe D
6
Devemos copiar este Candide Ordenar :"This is the best of all posibble worlds because it is the world that is, and so in the best possible world the array would already be sorted!"
echochamber
2
Eu, por exemplo, saúdo o nosso novo senhor de triagem. Todos saudam o classificador!
Bryson
299

Muitos anos atrás, eu inventei (mas nunca realmente implementei) o MiracleSort.

Start with an array in memory.
loop:
    Check to see whether it's sorted.
    Yes? We're done.
    No? Wait a while and check again.
end loop

Eventualmente, as partículas alfa que lançam bits nos chips de memória devem resultar em uma classificação bem-sucedida.

Para maior confiabilidade, copie a matriz para um local protegido e verifique as matrizes potencialmente classificadas em relação ao original.

Então, como você verifica a matriz potencialmente classificada em relação à original? Você apenas classifica cada matriz e verifica se elas correspondem. MiracleSort é o algoritmo óbvio a ser usado para esta etapa.

EDIT: Estritamente falando, este não é um algoritmo, pois não é garantido que seja finalizado. "Um algoritmo" não se qualifica como "um algoritmo pior"?

Keith Thompson
fonte
39
Suponho que se possa usar raios cósmicos para provar a correção desse algoritmo.
Ghord
1
Qual é o grande O disso? O(2^N)?
Mooing Duck
12
@MooingDuck: Eu não acho que ele realmente tem um grande O.
Keith Thompson
5
@MooingDuck: Estritamente falando, se não termina, não é um algoritmo, de acordo com o que eles me ensinaram na faculdade e com o artigo da Wikipedia .
21413 Keith Thompson
7
@Olathe: The Halting Problem diz que não podemos determinar para todos os programas se eles são interrompidos, mas há muitos programas para os quais podemos fazer essa determinação. Nós sabemos Quicksort e Bubblesoft parada, e nós sabemos que eles são algoritmos.
Keith Thompson
133

Quantum Bogosort

Um algoritmo de classificação que assume que a interpretação de muitos mundos da mecânica quântica está correta:

  1. Verifique se a lista está classificada. Caso contrário, destrua o universo.

Na conclusão do algoritmo, a lista será classificada no único universo que resta. Esse algoritmo leva o pior tempo O (N) e o tempo médio O (1). De fato, o número médio de comparações realizadas é 2: há 50% de chance de o universo ser destruído no segundo elemento, 25% de chance de ser destruído no terceiro, e assim por diante.

BioGeek
fonte
42
Mas o tempo deixa de existir no universo que você acabou de destruir. Portanto, um observador em um universo que você ainda não verificou não será capaz de dizer quanto do algoritmo foi executado. Assim, esse algoritmo sempre leva tempo O (1), pois as destruições anteriores do universo não existem mais.
Barry Brown
12
Sim, no único universo que observa a lista classificada, levou O (n) tempo para ser executado - quanto tempo levou em outros universos é irrelevante.
Nick Johnson
19
Esse algoritmo tem um problema muito maior, no entanto. Suponha que uma em 10 bilhões de vezes você concluirá por engano que uma lista é classificada quando não é. São 20! maneiras de classificar uma lista de 20 elementos. Após a classificação, os universos restantes serão aqueles em que a lista foi classificada corretamente e os 2,4 milhões de universos nos quais o algoritmo concluiu erroneamente que a lista foi classificada corretamente. Então, o que você tem aqui é um algoritmo para ampliar massivamente a taxa de erro de uma peça de máquina.
Nick Johnson
10
Este é obviamente o melhor algoritmo de classificação, não o pior.
Boann
11
Não seguir o conselho de Beetle pode resultar na destruição de todos os universos.
CrashCodes
60

Estou surpreso que ninguém tenha mencionado o sleepsort ainda ... Ou não o notei? De qualquer forma:

#!/bin/bash
function f() {
    sleep "$1"
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait

exemplo de uso:

./sleepsort.sh 5 3 6 3 6 3 1 4 7
./sleepsort.sh 8864569 7

Em termos de desempenho, é terrível (especialmente o segundo exemplo). Esperar quase 3,5 meses para classificar 2 números é meio ruim.

Kw4s
fonte
3
Isso parece ser uma O(N)espécie, mas, na verdade, é limitado pelo entanto, o sistema operacional implementa temporizadores.
precisa
7
De qualquer maneira, é provável que exista um crescimento melhor do que o bogosort.
Mooing Duck
8
Eu vejo uma condição de corrida lá.
5
Você pode alterar sleep "$1"para sleep "0.$(printf "%010d" $1)"para melhorar significativamente o desempenho. time ./sleepsort.sh 8864569 7depois é executado em 0,009s no meu laptop.
precisa
1
Isso é executado na complexidade O (N) (dependente, é claro, da implementação do timer), é uma classificação de bucket simples de forma diferente.
Qwerty01
60

Classificação do Jingle, conforme descrito aqui .

Você atribui cada valor da sua lista a uma criança diferente no Natal. As crianças, sendo seres humanos terríveis, compararão o valor de seus dons e se organizarão de acordo.

Curtis Lassam
fonte
50

Eu tive um palestrante que sugeriu uma geração de uma matriz aleatória, verificando se ela foi classificada e, em seguida, verificando se os dados eram iguais aos da matriz a ser classificada.

Melhor caso O (N) (bebê pela primeira vez!) Pior caso O (nunca)

Daniel
fonte
4
Mais interessante para analisar é o caso médio , que é ...?
Mooing Duck
4
Como dizem os melhores livros, isso é deixado como um exercício para o leitor!
Daniel
40
Mooing Duck: O (às vezes)
Ilya O.
1
@MooingDuck, precisamos saber a cardinalidade do tipo e distribuição de elementos usados ​​para gerar elementos aleatórios em matrizes aleatórias.
Exibir nome
5
A complexidade é O (N! * Z ^ N), onde Z é o tamanho do conjunto de valores possíveis e N é o comprimento da matriz.
jakubiszon
30

Se você mantiver o algoritmo significativo de qualquer forma, O(n!)é o pior limite superior possível.

Como verificar cada possibilidade de ordenar permutações de um conjunto tomará n!etapas, você não pode ficar pior do que isso.

Se você estiver executando mais etapas do que isso, o algoritmo não tem nenhum propósito realmente útil. Sem mencionar o seguinte algoritmo de classificação simples com O(infinity):

list = someList
while (list not sorted):
    doNothing
Yuval Adam
fonte
14
Mas leva O (n) para verificar se ele está classificado, assim você pode obter O (n * n!)
erikkallen
3
@erikkallen: Certamente, podemos criar um algoritmo para verificar se a classificação é pior que O (n). Por exemplo, para cada elemento da matriz, verifique se é maior que todos os anteriores, assim como a classificação por inserção funciona. Esse é um algoritmo O (n ^ 2), e eu tenho certeza que eu poderia pensar pior, pensando um pouco.
21810 David Thornley
7
@ David Thornley: o seguinte algoritmo de verificação talvez mostrasse o mesmo espírito que o bogosort: escolha dois elementos aleatórios, verifique se aquele com o índice menor é menor ou igual ao com o índice maior e repita. Mantenha uma matriz de bits quadrados para ver quais combinações já foram verificadas. Claro, verificando esta matriz também pode ser feito em um passeio aleatório ...
Svante
19

Bogobogosort. Sim, é uma coisa. para Bogobogosort, você Bogosort o primeiro elemento. Verifique se esse elemento está classificado. Sendo um elemento, será. Em seguida, adicione o segundo elemento e Bogosort esses dois até que sejam classificados. Então você adiciona mais um elemento, depois o Bogosort. Continue adicionando elementos e Bogosorting até finalmente fazer todos os elementos. Isso foi projetado para nunca ter sucesso com nenhuma lista considerável antes da morte pelo calor do universo.

Playnwinplayer
fonte
5
Santa mãe do código. Acho que podemos até fazer um curta de Bogolplex.
MrKekson
19

Você deve fazer alguma pesquisa sobre o emocionante campo dos algoritmos pessimais e da análise de simplicidade . Esses autores trabalham no problema de desenvolver uma classificação com um melhor caso pessimal (o melhor caso do seu bogosort é Omega (n), enquanto o slowsort (consulte o artigo) tem uma complexidade de tempo não polinomial do melhor caso).

Derrick Turk
fonte
19

Existe um tipo chamado bogobogosort. Primeiro, ele verifica os 2 primeiros elementos e os classifica de bogo. Em seguida, ele verifica os 3 primeiros, classifica-os e assim por diante.

Se a lista estiver fora de ordem a qualquer momento, ela será reiniciada novamente, classificando os 2 primeiros. O bogosort regular tem uma complexidade média de O(N!), esse algoritmo tem uma complexidade média deO(N!1!2!3!...N!)

Editar : para ter uma idéia de quão grande esse número é, para 20elementos, esse algoritmo leva uma média de 3.930093*10^158 anos , bem acima da morte por calor proposta pelo universo (se isso acontecer) de 10^100 anos ,

enquanto a classificação de mesclagem leva cerca de .0000004 segundos , a classificação de bolha .0000016 segundos e o bogosort leva 308 anos , 139 dias , 19 horas , 35 minutos , 22.306 segundos , assumindo que um ano seja 365.242 dias e um computador faz 250.000.000 de operações inteiras de 32 bits por segundo.

Edit2 : Esse algoritmo não é tão lento quanto o tipo de milagre "algoritmo", que provavelmente, como esse, fará com que o computador seja sugado pelo buraco negro antes de classificar com êxito 20 elemtnts, mas, se o fizesse, eu estimaria uma complexidade média de 2^(32(the number of bits in a 32 bit integer)*N)(the number of elements)*(a number <=10^40) anos ,

uma vez que a gravidade acelera o movimento alfa dos chips, e existem 2 ^ N estados, que são 2^640*10^40, ou cerca de 5.783*10^216.762162762 anos , embora se a lista começasse a ser classificada, sua complexidade seria apenas O(N)mais rápida que a classificação por mesclagem, que é apenas N log N no pior dos casos.

Edit3 : Esse algoritmo é realmente mais lento que a classificação milagrosa, pois o tamanho fica muito grande, digamos 1000, já que meu algoritmo teria um tempo de execução de 2.83*10^1175546 anos , enquanto o algoritmo de classificação milagrosa teria um tempo de execução de 1.156*10^9657 anos .

Beija-flor
fonte
1
ótima resposta trabalhada. triste ele não tem visibilidade
Swyx
16

Aqui estão dois tipos que eu vim com meu colega de quarto na faculdade

1) Verifique a ordem 2) Talvez tenha acontecido um milagre, vá para 1

e

1) verifique se está em ordem; caso contrário, 2) coloque cada elemento em um pacote e devolva-o para um servidor distante. Alguns desses pacotes retornarão em uma ordem diferente, então vá para 1

Seth
fonte
O segundo é quase o equivalente a um tipo de bozo. Primeiro é inteligente embora.
Mooing Duck
1
O primeiro é o Miracle Sort.
Charles
14

Sempre há o Bogobogosort (Bogoception!). Ele executa o Bogosort em subconjuntos cada vez maiores da lista e, em seguida, inicia tudo de novo se a lista nunca for classificada.

for (int n=1; n<sizeof(list); ++n) {
  while (!isInOrder(list, 0, n)) {
    shuffle(list, 0, n);
  }
  if (!isInOrder(list, 0, n+1)) { n=0; }
}
IceMetalPunk
fonte
5
Eu gosto da idéia de que este algoritmo é projetado para não terminar "antes da morte térmica do universo para qualquer lista considerável"
A.Grandt
10

1 Coloque seus itens para serem classificados nos cartões de índice
2 Jogue-os no ar em um dia ventoso, a 1,6 km de sua casa.
2 Jogue-os na fogueira e confirme que estão completamente destruídos.
3 Verifique o piso da sua cozinha para obter a ordem correta.
4 Repita se não estiver na ordem correta.

O melhor cenário é O (∞)

Edite acima com base na observação astuta de KennyTM.

Patrick Karcher
fonte
9
Não, isso é pior porque não há chance de sucesso. Como os cartões de índice entrariam em sua cozinha? Eles estão soprando lá fora. É chamado, uh, de meia-idade.
Patrick Karcher
Acho que ele quer dizer jogar as cartas no ar lá fora e depois checar seu andar lá dentro , onde é garantido que não haja cartas. Embora não seja um algoritmo "nomeado" ... é certamente pior!
Womp 9/04
10
@Patrick Quantum tunelamento.
Kennytm #
8
@KennyTM. Isso realmente me ocorreu. Há uma chance extremamente pequena, mas diferente de zero, de que qualquer objeto possa desaparecer e reaparecer em qualquer outro ponto do universo. Eu acho que isso poderia acontecer com milhares de cartões de índice. . . Oi. Dangit, meu algoritmo é falho . Eu resolvo isso . . .
Patrick Karcher
3
É como tomar chá e não chá ao mesmo tempo. Ou viaje no espaço usando uma unidade de improbabilidade infinita.
Barry Brown
9

O "o que você gostaria que fosse?" ordenar

  1. Anote a hora do sistema.
  2. Classifique usando o Quicksort (ou qualquer outra coisa razoavelmente sensata), omitindo a última troca.
  3. Anote a hora do sistema.
  4. Calcule o tempo necessário. A aritmética de precisão estendida é um requisito.
  5. Aguarde o tempo necessário.
  6. Execute a última troca.

Não apenas ele pode implementar qualquer valor O (x) concebível antes do infinito, o tempo gasto é comprovadamente correto (se você puder esperar tanto tempo).

david.pfx
fonte
8

Nada pode ser pior que o infinito.

Joseph Salisbury
fonte
38
Infinito + 1. Jinx, sem retorno.
Zombat 09/04
24
Não para valores extremamente grandes de 1;)
zombat
8
O que realmente me impressiona sobre o conceito de infinito é que você pode ter "tamanhos" diferentes de infinito. Por exemplo, considere o conjunto de todos os números inteiros - ele é infinito em tamanho. Agora considere o conjunto de todos os números pares - ele também é infinito em tamanho, mas também é claramente metade do tamanho do primeiro conjunto. Tamanhos infinitos, mas diferentes. Tão legal. O conceito de "tamanho" simplesmente não funciona no contexto do infinito.
zombat
4
@ zombat: Você está falando de cardinalidade, não de infinito como um símbolo que indica uma tendência na linha real / plano complexo.
Kennytm #
18
@zombat. O tamanho do conjunto de números inteiros pares é igual ao tamanho do conjunto de números inteiros, como mostra o fato de que você pode colocá-los em uma correspondência individual. Agora, existem mais números reais do que números inteiros, como mostrado pela primeira vez pelo Cantor.
21710 David Thornley
5

A classificação Bozo é um algoritmo relacionado que verifica se a lista está classificada e, se não, troca dois itens aleatoriamente. Ele tem as mesmas performances de melhor e pior caso, mas eu esperaria intuitivamente que o caso médio fosse mais longo que o Bogosort. É difícil encontrar (ou produzir) quaisquer dados sobre o desempenho desse algoritmo.

tloflin
fonte
5

Segmentos de π

Suponha que π contém todas as combinações possíveis de números finitos. Veja questão math.stackexchange

  1. Determine o número de dígitos necessários a partir do tamanho da matriz.
  2. Use segmentos de π lugares como índices para determinar como reordenar a matriz. Se um segmento exceder os limites de tamanho para essa matriz, ajuste o deslocamento decimal π e comece novamente.
  3. Verifique se a matriz reordenada está classificada. Se for woot, ajuste o deslocamento e comece novamente.
CrashCodes
fonte
4

O pior desempenho de O (() pode nem torná-lo um algoritmo, de acordo com alguns .

Um algoritmo é apenas uma série de etapas e você pode sempre piorar um pouco o ajuste para obter a saída desejada em mais etapas do que as anteriores. Alguém poderia propositadamente colocar o conhecimento do número de etapas executadas no algoritmo e fazê-lo terminar e produzir a saída correta somente após o Xnúmero de etapas ter sido realizado. Isso Xpode muito bem ser da ordem de O (n 2 ) ou O (n n! ) Ou qualquer que seja o algoritmo desejado. Isso aumentaria efetivamente seus limites de melhor caso e médio.

Mas o seu pior cenário não pode ser superado :)

Anurag
fonte
3

Meu algoritmo de classificação lenta favorito é o tipo stooge:

void stooges(long *begin, long *end) {
   if( (end-begin) <= 1 ) return;
   if( begin[0] < end[-1] ) swap(begin, end-1);
   if( (end-begin) > 1 ) {
      int one_third = (end-begin)/3;
      stooges(begin, end-one_third);
      stooges(begin+one_third, end);
      stooges(begin, end-one_third);
   }
}

O pior caso é a complexidade O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Outro algoritmo de classificação lenta é chamado de slowsort!

void slow(long *start, long *end) {
   if( (end-start) <= 1 ) return;
   long *middle = start + (end-start)/2;
   slow(start, middle);
   slow(middle, end);
   if( middle[-1] > end[-1] ) swap(middle-1, end-1);
   slow(start, end-1);
}

Este leva O(n ^ (log n))no melhor caso ... ainda mais lento que o Stoogesort.

Ben Goldberg
fonte
3
Recursive Bogosort (probably still O(n!){
if (list not sorted)
list1 = first half of list.
list 2 = second half of list.
Recursive bogosort (list1);
Recursive bogosort (list2);
list = list1 + list2
while(list not sorted)
    shuffle(list);
}
user3667082
fonte
2

Esta página é uma leitura interessante sobre o tópico: http://home.tiac.net/~cri_d/cri/2001/badsort.html

Meu favorito pessoal é o sillysort de Tom Duff:

/*
 * The time complexity of this thing is O(n^(a log n))
 * for some constant a. This is a multiply and surrender
 * algorithm: one that continues multiplying subproblems
 * as long as possible until their solution can no longer
 * be postponed.
 */
void sillysort(int a[], int i, int j){
        int t, m;
        for(;i!=j;--j){
                m=(i+j)/2;
                sillysort(a, i, m);
                sillysort(a, m+1, j);
                if(a[m]>a[j]){ t=a[m]; a[m]=a[j]; a[j]=t; }
        }
}
fsanches
fonte
2

Double bogosort

Escolha duas vezes e compare os resultados (apenas para ter certeza de que estão classificados), se não o fizer novamente

Viktor Mellgren
fonte
1

Você pode tornar qualquer algoritmo de classificação mais lento executando sua etapa "está classificada" aleatoriamente. Algo como:

  1. Crie uma matriz de booleanos do mesmo tamanho da matriz que você está classificando. Defina todos eles como false.
  2. Execute uma iteração de bogosort
  3. Escolha dois elementos aleatórios.
  4. Se os dois elementos forem classificados em relação um ao outro (i <j && matriz [i] <matriz [j]), marque os índices de ambos na matriz booleana como true. Caso contrário, comece de novo.
  5. Verifique se todos os booleanos na matriz são verdadeiros. Caso contrário, volte para 3.
  6. Feito.
Brendan Long
fonte
1

Sim, SimpleSort, em teoria ele é executado, no O(-1)entanto, isso é equivalente aoO(...9999) que, por sua vez, é equivalente a O (∞ - 1), que, como acontece, também é equivalente a O (∞). Aqui está minha implementação de exemplo:

/* element sizes are uneeded, they are assumed */
void
simplesort (const void* begin, const void* end)
{
  for (;;);
}
Joe D
fonte
1

Um que eu estava trabalhando envolve escolher dois pontos aleatórios e, se estiverem na ordem errada, inverter todo o subintervalos entre eles. Encontrei o algoritmo em http://richardhartersworld.com/cri_d/cri/2001/badsort.html , que diz que o caso médio é provavelmente algo em torno de O (n ^ 3) ou O (n ^ 2 log n) ( ele não tem muita certeza).

Eu acho que pode ser possível fazê-lo com mais eficiência, porque eu acho que pode ser possível fazer a operação de reversão no tempo O (1).

Na verdade, eu acabei de perceber que fazer isso faria tudo o que digo, talvez porque acabei de perceber que a estrutura de dados que eu tinha em mente colocaria o acesso aos elementos aleatórios em O (log n) e determinaria se seria necessário reverter em O (n )

AJMansfield
fonte
1

Randomsubsetsort.

Dada uma matriz de n elementos, escolha cada elemento com probabilidade 1 / n, randomize esses elementos e verifique se a matriz está classificada. Repita até classificar.

O tempo esperado é deixado como um exercício para o leitor.

Steven Armstrong
fonte