Esistono algoritmi di ordinamento peggiori di Bogosort (aka Monkey Sort)? [chiuso]


178

I miei colleghi mi hanno riportato indietro nel tempo ai miei giorni universitari con una discussione sugli algoritmi di ordinamento questa mattina. Abbiamo ricordato i nostri preferiti come StupidSort e uno di noi era sicuro di aver visto un algoritmo di ordinamento O(n!). Questo mi ha fatto iniziare a cercare gli algoritmi di ordinamento "peggiori" che ho trovato.

Abbiamo postulato che un ordinamento completamente casuale sarebbe piuttosto male (cioè randomizzare gli elementi - è in ordine? No? Randomizzare di nuovo), e mi sono guardato intorno e ho scoperto che apparentemente si chiama BogoSort, o Monkey Sort, o talvolta solo Ordinamento casuale .

Monkey Sort sembra avere prestazioni nel caso peggiore, prestazioni nel O(∞)migliore dei casi O(n)e prestazioni medie di O(n·n!).

Qual è l'algoritmo di ordinamento attualmente ufficiale accettato con le peggiori prestazioni di ordinamento medio (e quindi peggiore di O(n·n!))?


10
Quanti bogomips per bogosort? Le menti indagatrici vogliono sapere.
zombat,

13
Per chiarire, stai escludendo il caso banale in cui la prestazione del caso migliore è O (∞)?
tloflin,


6
Ho sentito che la specie di scimmia è anche conosciuta come "specie di ubriaco", un nome che trovo molto più evocativo.
Matteo Italia,

6
@Matteo Italia - o potrebbe essere chiamato "Toddler Sort" come può testimoniare chiunque abbia 2 anni.
Martin Capodici,

Risposte:


442

Dalla pagina degli algoritmi esoterici di David Morgan-Mar : Intelligent Design Sort

introduzione

L'ordinamento del design intelligente è un algoritmo di ordinamento basato sulla teoria del design intelligente.

Descrizione dell'algoritmo

La probabilità che l'elenco di input originale sia nell'ordine esatto in cui si trova è 1 / (n!). C'è una probabilità così piccola di ciò che è chiaramente assurdo affermare che ciò è accaduto per caso, quindi deve essere stato consciamente messo in quell'ordine da un Sorter intelligente. Pertanto è lecito ritenere che sia già stato ordinato in modo ottimale in qualche modo che trascenda la nostra ingenua comprensione mortale dell '"ordine crescente". Qualsiasi tentativo di modificare tale ordine per conformarsi ai nostri preconcetti lo renderebbe in realtà meno ordinato.

Analisi

Questo algoritmo è costante nel tempo e ordina l'elenco sul posto, non richiede alcuna memoria aggiuntiva. In realtà, non richiede nemmeno nulla di quel materiale tecnologico sospetto. Lodate il sorter!

Risposta

Gary Rogers scrive:

Rendere costante l'ordinamento nel tempo nega il potere di The Sorter. The Sorter esiste al di fuori del tempo, quindi il tipo è senza tempo. Richiedere tempo per convalidare l'ordinamento riduce il ruolo del Sorter. Quindi ... questo particolare tipo è imperfetto e non può essere attribuito a "The Sorter".

Eresia!


94
Conosciuto anche come "Ordinamento degli assunti": supponi che l'elenco sia ordinato, ritorna!
BioGeek

42
+100 - questa risposta è fatta con una vittoria pura al 100%.
womp

11
Hey! Non dimenticare "Ordinamento indeciso" (noto anche come "Ordinamento di Schrodinger" o "Ordinamento quantico"), in cui l'elenco può essere ordinato o meno, tuttavia controllandolo si rivelerà se lo è o meno. Ecco il mio esempio di implementazione: 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
Dobbiamo duplicare questo Candide Sort :"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
Per uno, accolgo con favore il nostro nuovo signore dell'ordinamento. Tutti salutano il selezionatore!
Bryson,

299

Molti anni fa, ho inventato (ma mai effettivamente implementato) 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

Alla fine, le particelle alfa che lanciano i bit nei chip di memoria dovrebbero risultare in un ordinamento riuscito.

Per una maggiore affidabilità, copiare l'array in una posizione protetta e verificare gli array potenzialmente ordinati rispetto all'originale.

Quindi, come si controlla l'array potenzialmente ordinato rispetto all'originale? Basta ordinare ogni array e verificare se corrispondono. MiracleSort è l'algoritmo ovvio da utilizzare per questo passaggio.

EDIT: A rigor di termini, questo non è un algoritmo, dal momento che non è garantito per terminare. "Non un algoritmo" si qualifica come "un algoritmo peggiore"?


39
Presumo che si possano usare i raggi cosmici per dimostrare la correttezza di questo algoritmo.
gh

1
Qual è la grande O di questo? O(2^N)?
Mooing Duck,

12
@MooingDuck: non credo che abbia una grande O.
Keith Thompson,

5
@MooingDuck: A rigor di termini, se non termina non è un algoritmo, secondo quanto mi hanno insegnato al college e l' articolo di Wikipedia .
Keith Thompson,

7
@Olathe: The Halting Problem dice che non possiamo determinare se tutti i programmi si fermano, ma ci sono molti programmi per i quali possiamo prendere quella decisione. Sappiamo che Quicksort e Bubblesoft si fermano e sappiamo che sono algoritmi.
Keith Thompson,

133

Quantum Bogosort

Un algoritmo di ordinamento che presuppone che l'interpretazione a molti mondi della meccanica quantistica sia corretta:

  1. Verificare che l'elenco sia ordinato. Altrimenti, distruggi l'universo.

Alla conclusione dell'algoritmo, l'elenco verrà ordinato nell'universo rimasto in piedi. Questo algoritmo richiede il tempo O (N) e il caso O (1) nel caso peggiore. In effetti, il numero medio di confronti eseguiti è 2: c'è una probabilità del 50% che l'universo venga distrutto sul secondo elemento, una probabilità del 25% che venga distrutto sul terzo e così via.


42
Ma il tempo cessa di esistere nell'universo che hai appena distrutto. Quindi un osservatore in un universo che non hai ancora verificato non sarà in grado di dire quanta parte dell'algoritmo è stata eseguita. Pertanto, questo algoritmo richiede sempre O (1) tempo, poiché le precedenti distruzioni dell'universo non esistono più.
Barry Brown,

12
Sì, nell'universo che osserva l'elenco ordinato, ci è voluto O (n) tempo per eseguire - quanto tempo ha impiegato in altri universi è irrilevante.
Nick Johnson,

19
Questo algoritmo ha tuttavia un problema molto più grande. Supponiamo che uno su 10 miliardi di volte concluderai erroneamente un elenco ordinato quando non lo è. Ce ne sono 20! modi per ordinare un elenco di 20 elementi. Dopo l'ordinamento, gli universi rimanenti saranno quelli in cui l'elenco è stato ordinato correttamente e i 2,4 milioni di universi in cui l'algoritmo ha erroneamente concluso che l'elenco è stato ordinato correttamente. Quindi quello che hai qui è un algoritmo per ingrandire in modo massiccio il tasso di errore di un macchinario.
Nick Johnson,

10
Questo è ovviamente il miglior algoritmo di ordinamento, non il peggiore.
Boann,

11
La mancata guida del consiglio di Beetle può comportare la distruzione di tutti gli universi.
CrashCodes

60

Sono sorpreso che nessuno abbia ancora menzionato sleepsort ... O non l'ho notato? Comunque:

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

esempio di utilizzo:

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

In termini di prestazioni è terribile (specialmente il secondo esempio). Aspettare quasi 3,5 mesi per ordinare 2 numeri è un po 'male.


3
Questo sembra essere un O(N)tipo, ma in verità è vincolato da tuttavia il sistema operativo implementa i timer.
Mooing Duck,

7
In qualsiasi modo lo tagli, questo probabilmente mostra una crescita migliore del bogosort.
Mooing Duck il

8
Vedo una condizione di gara lì.

5
È possibile modificare la sleep "$1"a sleep "0.$(printf "%010d" $1)"prestazioni per migliorare notevolmente. time ./sleepsort.sh 8864569 7quindi viene eseguito in 0,009 secondi sul mio laptop.
Sam Kellett,

1
Questo funziona in complessità O (N) (dipende ovviamente dall'implementazione del timer), è un semplice tipo di bucket in forma diversa.
Qwerty01

60

Jingle Sort, come descritto qui .

Dai Natale a ciascun valore del tuo elenco a un bambino diverso. I bambini, essendo terribili esseri umani, confronteranno il valore dei loro doni e si sistemeranno di conseguenza.


50

Ho avuto un docente che una volta ha suggerito di generare un array casuale, controllando se fosse ordinato e quindi controllando se i dati erano gli stessi dell'array da ordinare.

Caso migliore O (N) (prima volta bambino!) Caso peggiore O (mai)


4
Più interessante da analizzare è il caso medio , che è ...?
Mooing Duck,

4
Come dicono tutti i migliori libri di testo, questo è lasciato come esercizio per il lettore!
Daniel,

40
Mooing Duck: O (a volte)
Ilya O.

1
@MooingDuck quindi abbiamo bisogno di conoscere la cardinalità del tipo di elemento e della distribuzione utilizzata per generare elementi casuali in array casuali.
Visualizza nome

5
La complessità è O (N! * Z ^ N) dove Z è la dimensione dell'insieme dei valori possibili e N è la lunghezza dell'array.
Jakubiszon,

30

Se mantieni l'algoritmo significativo in qualche modo, O(n!)è il limite superiore peggiore che puoi ottenere.

Dal momento che il controllo di ogni possibilità di permutazioni di un set da ordinare richiederà alcuni n!passaggi, non si può andare peggio di così.

Se stai facendo più passaggi di quello, l'algoritmo non ha un reale scopo utile. Per non parlare del seguente algoritmo di ordinamento semplice con O(infinity):

list = someList
while (list not sorted):
    doNothing

14
Ma ci vuole O (n) per verificare se è ordinato, quindi puoi ottenere O (n * n!)
erikkallen

3
@erikkallen: Certamente possiamo escogitare un algoritmo per verificare l'ordinamento peggiore di O (n). Ad esempio, per ogni elemento dell'array, verificare che sia maggiore di tutti i precedenti, proprio come funziona l'ordinamento per inserzione. Questo è un algoritmo O (n ^ 2), e sono sicuro che potrei escogitare qualcosa di peggio, dato un piccolo pensiero.
David Thornley,

7
@David Thornley: il seguente algoritmo di controllo mostrerebbe forse lo stesso spirito del bogosort: scegli due elementi casuali, controlla che quello con l'indice più piccolo sia più piccolo o uguale a quello con l'indice più grande, quindi ripeti. Mantieni una matrice di bit quadrati per vedere quali combinazioni sono già state verificate. Certo, controllare questa matrice potrebbe anche essere fatto in una passeggiata casuale ...
Svante

19

Bogobogosort. Sì, è una cosa. a Bogobogosort, Bogosort è il primo elemento. Verifica se quell'elemento è stato ordinato. Essendo un elemento, lo sarà. Quindi aggiungi il secondo elemento e Bogosort quei due fino a quando non viene ordinato. Quindi aggiungi un altro elemento, quindi Bogosort. Continua ad aggiungere elementi e Bogosorting fino a quando non hai completato tutti gli elementi. Questo è stato progettato per non riuscire mai con un elenco considerevole prima della morte per calore dell'universo.


5
Santa madre del codice. Penso che possiamo persino fare un cortometraggio Bogolplex.
MrKekson,

19

Dovresti fare qualche ricerca nel campo entusiasmante degli algoritmi pessimali e dell'analisi di simplexità . Questi autori lavorano sul problema di sviluppare una specie con un caso pessimale (il caso migliore del tuo bogosort è Omega (n), mentre slowsort (vedi il documento) ha una complessità temporale non polinomiale nel caso migliore).


19

C'è una specie chiamata bogobogosort. Innanzitutto, controlla i primi 2 elementi e li ordina. Successivamente controlla i primi 3, li ordina, e così via.

Se la lista dovesse essere fuori servizio in qualsiasi momento, si riavvia bogosortando nuovamente i primi 2. Il bogosort regolare ha una complessità media di O(N!), questo algoritmo ha una complessità media diO(N!1!2!3!...N!)

Modifica : per darti un'idea di quanto sia grande questo numero, per gli 20elementi, questo algoritmo richiede una media di 3.930093*10^158 anni , ben al di sopra della morte termica dell'universo proposta (se succede) di 10^100 anni ,

considerando merge richiede sorta attorno .0000004 secondi , bolla ordinamento .0000016 secondi , e Stupid Sort richiede 308 anni , 139 giorni , 19 ore , 35 minuti , 22.306 secondi , assumendo un anno è 365.242 giorni e un computer fa 250.000.000 operazioni a 32 bit interi per secondo.

Edit2 : questo algoritmo non è lento come l'ordinamento miracoloso "algoritmo", che probabilmente, come questo ordinamento, farà risucchiare il computer nel buco nero prima che ordinasse con successo 20 elemtts, ma se lo facesse, stimerei una complessità media di 2^(32(the number of bits in a 32 bit integer)*N)(the number of elements)*(a number <=10^40) anni ,

poiché la gravità accelera il movimento dei chip alfa e ci sono 2 ^ N stati, che è 2^640*10^40, o circa 5.783*10^216.762162762 anni , anche se se l'elenco fosse iniziato ordinato, la sua complessità sarebbe solo O(N), più veloce di unire l'ordinamento, che è solo N log N anche nel peggiore dei casi.

Edit3 : questo algoritmo è in realtà più lento dell'ordinamento miracoloso poiché le dimensioni diventano molto grandi, diciamo 1000, poiché il mio algoritmo avrebbe un tempo di esecuzione di 2.83*10^1175546 anni , mentre l'algoritmo di ordinamento miracoloso avrebbe un tempo di esecuzione di 1.156*10^9657 anni .


1
ottima risposta lavorata. triste non ha visibilità
swyx

16

Ecco 2 tipi che ho escogitato con il mio compagno di stanza al college

1) Controlla l'ordine 2) Forse è successo un miracolo, vai a 1

e

1) controlla se è in ordine, se non 2) metti ogni elemento in un pacchetto e rimbalzalo da un server distante a te stesso. Alcuni di questi pacchetti torneranno in un ordine diverso, quindi vai a 1


Il secondo è quasi l'equivalente di una specie di bozo. Il primo è però intelligente.
Mooing Duck,

1
Il primo è Miracle Sort.
Charles

14

C'è sempre il Bogobogosort (Bogoception!). Esegue Bogosort su sottoinsiemi sempre più grandi dell'elenco e quindi ricomincia da capo se l'elenco non viene mai ordinato.

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; }
}

5
Mi piace l'idea che questo algoritmo sia progettato per non finire mai "prima della morte dell'Universo per un elenco considerevole"
A.Grandt,

10

1 Metti i tuoi oggetti per essere ordinati su schede
2 2 Lanciali in aria in una giornata ventosa, a un miglio da casa.
2 Gettali in un falò e conferma che sono completamente distrutti.
3 Controlla il pavimento della tua cucina per l'ordinamento corretto.
4 Ripetere se non è l'ordine corretto.

Il miglior caso scenerio è O (∞)

Modifica sopra basato sull'osservazione astuta di KennyTM.


9
No, questo è peggio perché non c'è alcuna possibilità che abbia successo. Come entrerebbero le schede nella tua cucina? Stanno soffiando fuori. Si chiama buttheadsort.
Patrick Karcher,

Penso che significhi lanciare le carte in aria fuori , e quindi controllare il tuo pavimento all'interno , dove è garantito che non ci siano carte. Sebbene non sia un algoritmo "chiamato" ... è sicuramente peggio!
womp

10
@Patrick Quantum tunneling.
kennytm,

8
@KennyTM. Mi era effettivamente venuto in mente. Esiste una possibilità estremamente piccola ma diversa da zero che qualsiasi oggetto possa scomparire e riapparire in qualsiasi altro punto dell'universo. Immagino che potrebbe succedere a mille schede. . . Oi. Dangit, il mio algoritmo è difettoso . Lo aggiusterò . . .
Patrick Karcher,

3
È un po 'come prendere il tè e senza tè allo stesso tempo. O viaggi nello spazio usando un'infinita unità di improbabilità.
Barry Brown,

9

Il "cosa vorresti che fosse?" ordinare

  1. Nota l'ora di sistema.
  2. Ordina usando Quicksort (o qualsiasi altra cosa ragionevolmente ragionevole), omettendo l'ultimo scambio.
  3. Nota l'ora di sistema.
  4. Calcola il tempo richiesto. L'aritmetica di precisione estesa è un requisito.
  5. Attendi il tempo richiesto.
  6. Esegui l'ultimo scambio.

Non solo può implementare qualsiasi valore concepibile O (x) inferiore all'infinito, ma il tempo impiegato è dimostrabilmente corretto (se puoi aspettare così a lungo).


8

Niente può essere peggio dell'infinito.


38
Infinito + 1. Jinx, nessun ritorno.
zombat,

24
Non per valori estremamente grandi di 1;)
zombat

8
Ciò che mi colpisce davvero del concetto di infinito è che puoi avere "dimensioni" diverse di infinito. Ad esempio, considera l'insieme di tutti i numeri interi - è di dimensioni infinite. Consideriamo ora l'insieme di tutti persino interi - è anche infinita in termini di dimensioni, ma è anche chiaramente la metà delle dimensioni del primo set. Entrambi infiniti, ma di dimensioni diverse. Così impressionante. Il concetto di "dimensione" semplicemente non funziona nel contesto dell'infinito.
zombat,

4
@zombat: stai parlando di cardinalità, non di infinito come simbolo che indica una tendenza sulla linea reale / piano complesso.
kennytm,

18
@zombat. La dimensione dell'insieme degli interi pari è uguale alla dimensione dell'insieme degli interi, come dimostra il fatto che è possibile inserirli in una corrispondenza uno a uno. Ora, ci sono più numeri reali che numeri interi, come mostrato per la prima volta da Cantor.
David Thornley,

5

L'ordinamento Bozo è un algoritmo correlato che controlla se l'elenco è ordinato e, in caso contrario, scambia due elementi a caso. Ha le stesse prestazioni migliori e peggiori, ma mi aspetto intuitivamente che il caso medio sia più lungo di Bogosort. È difficile trovare (o produrre) dati sulle prestazioni di questo algoritmo.


5

Segmenti di π

Supponiamo che π contenga tutte le possibili combinazioni di numeri finiti. Vedi la domanda di math.stackexchange

  1. Determinare il numero di cifre necessarie dalla dimensione dell'array.
  2. Utilizzare segmenti di punti π come indici per determinare come riordinare l'array. Se un segmento supera i limiti delle dimensioni per questo array, regolare l'offset decimale π e ricominciare.
  3. Controllare se l'array riordinato è ordinato. Se è woot, altrimenti regola l'offset e ricomincia.

4

Una prestazione nel caso peggiore di O (∞) potrebbe anche non renderlo un algoritmo secondo alcuni .

Un algoritmo è solo una serie di passaggi e puoi sempre fare di peggio modificandolo un po 'per ottenere l'output desiderato in più passaggi di quanto non fosse in precedenza. Si potrebbe mettere intenzionalmente la conoscenza del numero di passaggi Xeseguiti nell'algoritmo e farlo terminare e produrre l'output corretto solo dopo aver eseguito il numero di passaggi. Questo Xpotrebbe benissimo essere dell'ordine di O (n 2 ) o O (n n! ) O qualsiasi altra cosa l'algoritmo desiderato fare. Ciò aumenterebbe effettivamente i limiti del caso migliore e medio.

Ma il tuo scenario peggiore non può essere superato :)


3

Il mio algoritmo di ordinamento lento preferito è l'ordinamento fantoccio:

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);
   }
}

La complessità del caso peggiore è O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Un altro algoritmo di ordinamento lento si chiama 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);
}

Questo O(n ^ (log n))nel migliore dei casi ... anche più lento di un tirapiedi.


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);
}

2

Questa pagina è una lettura interessante sull'argomento: http://home.tiac.net/~cri_d/cri/2001/badsort.html

Il mio preferito è il sillysort di 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; }
        }
}

2

Doppio bogosort

Bogosort due volte e confronta i risultati (solo per essere sicuro che sia ordinato) se non lo fai di nuovo


1

È possibile rallentare qualsiasi algoritmo di ordinamento eseguendo il passaggio "è ordinato" in modo casuale. Qualcosa di simile a:

  1. Crea un array di valori booleani delle stesse dimensioni dell'array che stai ordinando. Impostali tutti su false.
  2. Esegui un'iterazione di bogosort
  3. Scegli due elementi casuali.
  4. Se i due elementi sono ordinati l'uno rispetto all'altro (i <j && array [i] <array [j]), contrassegnare gli indici di entrambi sull'array booleano su true. Altrimenti, ricominciare.
  5. Controlla se tutti i booleani nell'array sono veri. In caso contrario, tornare a 3.
  6. Fatto.

1

Sì, SimpleSort, in teoria funziona O(-1)ma questo è equivalente alO(...9999) quale è a sua volta equivalente a O (∞ - 1), che come accade equivale anche a O (∞). Ecco la mia implementazione di esempio:

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

1

Uno a cui stavo solo lavorando riguarda la selezione di due punti casuali e, se sono nell'ordine sbagliato, invertendo l'intera sottorange tra di loro. Ho trovato l'algoritmo su http://richardhartersworld.com/cri_d/cri/2001/badsort.html , che dice che il caso medio è probabilmente da qualche parte intorno a O (n ^ 3) o O (n ^ 2 log n) ( non è davvero sicuro).

Penso che potrebbe essere possibile farlo in modo più efficiente, perché penso che potrebbe essere possibile eseguire l'operazione di inversione nel tempo O (1).

In realtà, mi sono appena reso conto che farlo avrebbe reso tutto ciò che dico forse perché mi sono appena reso conto che la struttura di dati che avevo in mente avrebbe messo l'accesso agli elementi casuali su O (log n) e determinare se ha bisogno di invertire su O (n ).


1

Randomsubsetsort.

Data una matrice di n elementi, scegliere ogni elemento con probabilità 1 / n, randomizzare questi elementi e verificare se la matrice è ordinata. Ripeti fino all'ordinamento.

Il tempo previsto viene lasciato come esercizio per il lettore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.