web-dev-qa-db-fra.com

Existe-t-il des algorithmes de tri moins bons que Bogosort (a.k.a Monkey Sort)?

Mes collègues m'ont ramené à l'époque universitaire à une discussion sur les algorithmes de tri ce matin. Nous avons évoqué nos favoris comme StupidSort , et l'un de nous était certain d'avoir déjà vu un algorithme de tri qui s'appelait O(n!). Cela m'a permis de commencer à chercher les "pires" algorithmes de tri que j'ai pu trouver.

Nous avons postulé qu'un type complètement aléatoire serait assez mauvais (c.-à-d. Randomiser les éléments - est-il en ordre? Non? Randomize à nouveau), et j'ai regardé autour de moi pour découvrir qu'il s'appelait apparemment BogoSort, ou Monkey Sort, ou parfois juste un tri aléatoire .

Monkey Sort semble avoir la pire performance de O(∞), une meilleure performance de O(n) et une performance moyenne de O(n·n!).

Existe-t-il des algorithmes nommés dont les performances moyennes sont inférieures à celles de O(n·n!)? Ou sont-ils simplement plus ridicules que Monkey Sort en général?

163
womp

Depuis la page des algorithmes ésotériques de David Morgan-Mar : Tri par conception intelligente

Introduction

Le type de conception intelligente est un algorithme de tri basé sur la théorie de la conception intelligente.

Description de l'algorithme

La probabilité que la liste d’entrée originale soit dans l’ordre exact est de 1/(n!). Il y a une si petite probabilité que cela soit clairement absurde de dire que cela est arrivé par hasard. Il a donc dû être consciemment placé dans cet ordre par une trieuse intelligente. Par conséquent, il est prudent de supposer que le tri est déjà optimal de manière à transcender notre compréhension naïve des mortels de "l'ordre croissant". Toute tentative visant à modifier cet ordre afin de se conformer à nos propres idées préconçues le rendrait en réalité moins ordonné.

Analyse

Cet algorithme est constant dans le temps et trie la liste sur place, ne nécessitant aucune mémoire supplémentaire. En fait, il n’a même pas besoin de ces technologies informatiques suspectes. Louez la trieuse!

Commentaires

Gary Rogers écrit:

Rendre le tri constant dans le temps nie le pouvoir de The Sorter. La trieuse existe en dehors du temps, elle est donc intemporelle. Demander du temps pour valider le tri diminue le rôle de la trieuse. Ainsi ... cette sorte particulière est imparfaite et ne peut être attribuée à 'The Sorter'.

Hérésie!

424
BioGeek

Il y a de nombreuses années, j'ai inventé (mais jamais réellement mis en œuvre) 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

Finalement, les particules alpha retournant des bits dans les puces de mémoire devraient permettre un tri réussi.

Pour plus de fiabilité, copiez le tableau dans un emplacement blindé et comparez les tableaux potentiellement triés par rapport à l'original.

Alors, comment vérifiez-vous le tableau potentiellement trié par rapport à l'original? Vous venez de trier chaque tableau et de vérifier si elles correspondent. MiracleSort est l'algorithme évident à utiliser pour cette étape.

EDIT: Strictement parlant, il ne s'agit pas d'un algorithme, car sa terminaison n'est pas garantie. Est-ce que "pas un algorithme" est qualifié de "pire algorithme"?

289
Keith Thompson

Quantum Bogosort

Un algorithme de tri qui suppose que l'interprétation de la mécanique quantique dans de nombreux mondes est correcte:

  1. Vérifiez que la liste est triée. Sinon, détruisez l'univers.

A la fin de l'algorithme, la liste sera triée dans le seul univers restant debout. Cet algorithme prend le pire cas O(N) et le cas moyen O(1) temps. En fait, le nombre moyen de comparaisons effectuées est de 2: il y a 50% de chances que l'univers soit détruit sur le deuxième élément, 25% de chance qu'il soit détruit le troisième, et ainsi de suite.

128
BioGeek

Je suis surpris que personne n'ait encore parlé de Sleepsort ... Ou est-ce que je ne l'ai pas remarqué? En tous cas:

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

exemple d'utilisation:

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

En termes de performances, c'est terrible (surtout le deuxième exemple). Attendre près de trois mois et demi pour trier deux nombres est un peu mauvais.

55
Kw4s

Jingle Sort, comme décrit ici .

Vous donnez chaque valeur de votre liste à un enfant différent à Noël. Les enfants, étant des êtres humains affreux, vont comparer la valeur de leurs dons et se trier en conséquence.

55
Curtis Lassam

Un conférencier m'a suggéré une fois de générer un tableau aléatoire, en vérifiant si celui-ci était trié, puis en vérifiant si les données étaient identiques au tableau à trier.

Meilleur cas O(N) (premier bébé!) Le pire des cas O (Jamais)

47
Daniel

Si vous maintenez l'algorithme significatif, O(n!) est la pire limite supérieure que vous puissiez obtenir.

Étant donné que la vérification de chaque possibilité de permutation d'un ensemble à trier prend des étapes n!, Vous ne pouvez pas faire pire.

Si vous faites plus d’étapes que cela, alors l’algorithme n’a pas de véritable utilité. Sans parler de l'algorithme de tri simple suivant avec O(infinity):

list = someList
while (list not sorted):
    doNothing
30
Yuval Adam

Vous devriez faire des recherches dans le domaine passionnant de algorithmes de Pessimal et analyse de simplexité . Ces auteurs travaillent sur le problème du développement d'une sorte avec un meilleur cas pessimal (le meilleur cas de votre bogosort est Omega (n), alors que ralentir (voir document) a une complexité temporelle dans le meilleur des cas non polynomial).

19
Derrick Turk

Bogobogosort. Oui c'est une chose. à Bogobogosort, vous Bogosort le premier élément. Vérifiez pour voir si cet élément est trié. Être un élément, ce sera. Ensuite, vous ajoutez le deuxième élément et Bogosort ces deux jusqu'à ce qu'il soit trié. Ensuite, vous ajoutez un élément supplémentaire, puis Bogosort. Continuez à ajouter des éléments et Bogosorting jusqu'à ce que tous les éléments soient enfin terminés. Cela a été conçu pour ne jamais réussir avec une liste considérable avant la mort de chaleur de l'univers.

17
Playnwinplayer

Voici 2 sortes je suis venu avec mon colocataire à l'université

1) Vérifiez l'ordre 2) Peut-être un miracle s'est-il passé, allez à 1

et

1) vérifiez si tout est en ordre, sinon 2) mettez chaque élément dans un paquet et renvoyez-le à un serveur distant. Certains de ces paquets vont revenir dans un ordre différent, passez à 1

16
Seth

Il y a une sorte qui s'appelle bogobogosort. Tout d'abord, il vérifie les 2 premiers éléments et les corrige. Ensuite, il vérifie les 3 premiers, les corrige, etc. Si la liste est hors d'usage à tout moment, elle redémarre en modifiant à nouveau les 2 premiers. Bogosort standard a une complexité moyenne de O (N!), Cet algorithme a une complexité moyenne de O (N! 1! 2! 3! ... N!) Edit: Pour vous donner une idée de la taille de ce nombre, pour 20 éléments, cet algorithme prend en moyenne 3,93,0093 * 10 ^ 158 ans, bien au-dessus de la mort de chaleur proposée de l'univers (si cela se produit) de 10 ^ 100 ans, alors que le tri par fusion prend environ 0, 00004 secondes, le tri à bulle .0000016 secondes, et bogosort prend 308 ans, 139 jours, 19 heures, 35 minutes, 22,306 secondes, en supposant qu'une année correspond à 365,242 jours et qu'un ordinateur effectue 250 000 000 d'opérations d'entier 32 bits par seconde. Edit2: Cet algorithme n’est pas aussi lent que le tri miracle "algorithm", qui, probablement, obtiendra l’ordinateur aspiré dans le trou noir avant de trier avec succès 20 éléments, mais si c’était le cas, j’estimerais une complexité moyenne. de 2 ^ (32 (le nombre de bits dans un entier de 32 bits) N) (le nombre d'éléments) (un nombre <= 10 ^ 40 ans, car la gravité accélère le déplacement alpha des puces, et il y a 2 ^ N états, ce qui correspond à 2 ^ 640 * 10 ^ 40, ou environ 5,773 * 10 ^ 216.762162762 ans, bien que si la liste était triée au début, sa complexité serait uniquement de O (N), plus rapide que le tri par fusion, ce qui n’est que N log N même dans le pire des cas Edit3: Cet algorithme est en réalité plus lent que le tri miracle car la taille devient très grande, disons 1000, car mon algorithme aurait une durée d’exécution de 2,83 * 10 ^ 1175546 ans, L'algorithme de tri miracle aurait une durée d'exécution de 1,156 * 10 ^ 9657 ans.

14
bacca2002

Il y a toujours le Bogobogosort (Bogoception!). Il exécute Bogosort sur des sous-ensembles de plus en plus volumineux de la liste, puis recommence depuis le début si la liste n'est jamais triée.

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

1 Mettez vos objets à trier sur des fiches
2 Jetez-les dans les airs par une journée venteuse, à un mille de votre maison.
2 Jetez-les dans un feu de joie et confirmez qu'ils sont complètement détruits.
3 Vérifiez le bon ordre dans le sol de votre cuisine.
4 Répétez l'opération si l'ordre n'est pas correct.

Le meilleur scénario est O ()

Edit ci-dessus, basé sur une observation astucieuse de KennyTM.

10
Patrick Karcher

Le "que voudriez-vous qu'il soit?" Trier

  1. Notez l'heure du système.
  2. Triez à l'aide de Quicksort (ou de toute autre option raisonnable), en omettant le dernier échange.
  3. Notez l'heure du système.
  4. Calculez le temps requis. Une arithmétique de précision étendue est une exigence.
  5. Attendez le temps requis.
  6. Effectuer le dernier échange.

Non seulement il peut implémenter n'importe quelle valeur concevable O(x) inférieure à l'infini, mais le temps pris est parfaitement correct (si vous pouvez attendre aussi longtemps).

9
david.pfx

Rien ne peut être pire que l'infini.

7
Joseph Salisbury

Segments de π

Supposons que π contienne toutes les combinaisons de nombres finis possibles. Voir question math.stackexchange

  1. Déterminez le nombre de chiffres nécessaires à partir de la taille du tableau.
  2. Utilisez des segments de π places comme index pour déterminer comment réorganiser le tableau. Si un segment dépasse les limites de taille pour ce tableau, ajustez le décalage décimal π et recommencez.
  3. Vérifiez si le tableau re-ordonné est trié. Si c'est le cas, ajustez le décalage et recommencez.
5
CrashCodes

Le tri Bozo est un algorithme associé qui vérifie si la liste est triée et, dans le cas contraire, permute deux éléments de manière aléatoire. Il a les mêmes performances dans les cas les meilleurs et les moins favorables, mais je m'attendrais intuitivement à ce que la moyenne des cas soit plus longue que celle de Bogosort. Il est difficile de trouver (ou de produire) des données sur les performances de cet algorithme.

5
tloflin

Une pire performance de O (performance) pourrait même ne pas en faire un algorithme selon quelques-uns .

Un algorithme est juste une série d'étapes et vous pouvez toujours faire pire en le peaufinant un peu pour obtenir la sortie souhaitée en plus d'étapes que par le passé. On pourrait délibérément mettre la connaissance du nombre d'étapes prises dans l'algorithme et le faire terminer et produire la sortie correcte uniquement après X nombre d'étapes effectuées. Ce X pourrait très bien être de l’ordre de O (n2) ou O (nn!) ou quel que soit l'algorithme désiré. Cela augmenterait efficacement les limites de son scénario optimal et moyen.

Mais votre pire scénario ne peut pas être dépassé :)

4
Anurag
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);
}
3
user3667082

Mon algorithme de tri lent préféré est le tri 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);
   }
}

Le cas le plus complexe est O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Un autre algorithme de tri lent est en réalité nommé ralentissement!

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

Celui-ci prend O(n ^ (log n)) dans le meilleur des cas ... même plus lent que stoogesort.

3
Ben Goldberg

Cette page est une lecture intéressante sur le sujet: http://home.tiac.net/~cri_d/cri/2001/badsort.html

Mon préféré est le 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; }
        }
}
2
fsanches

Double bogosort

Bogosort deux fois et comparez les résultats (juste pour être sûr qu'il soit bien trié) sinon recommencez

2
Viktor Mellgren

L'une des tâches sur lesquelles je travaillais consiste à choisir deux points aléatoires et, s'ils sont dans le mauvais ordre, à inverser toute la sous-gamme entre eux. J'ai trouvé l'algorithme sur http://richardhartersworld.com/cri_d/cri/2001/badsort.html , qui indique que le cas moyen se situe probablement quelque part autour de O (n ^ 3) ou O ( n ^ 2 log n) (il n'est pas vraiment sûr).

Je pense qu’il serait peut-être possible de le faire plus efficacement, car je pense qu’il serait possible de faire l’opération d’inversion dans O(1) temps.

En fait, je viens de me rendre compte que faire cela ferait tout ce que je dirais peut-être parce que je venais de réaliser que la structure de données que je pensais envisageait l'accès aux éléments aléatoires en O (log n) et en déterminant s'il fallait inverser en O (n ).

1
AJMansfield

Vous pouvez ralentir n'importe quel algorithme de tri en exécutant votre étape "Est-il trié" de manière aléatoire? Quelque chose comme:

  1. Créez un tableau de booléens de la même taille que celui que vous triez. Définissez-les tous sur false.
  2. Exécuter une itération de bogosort
  3. Choisissez deux éléments aléatoires.
  4. Si les deux éléments sont triés les uns par rapport aux autres (i <j && array [i] <array [j]), marquez les index des deux sur le tableau booléen à true. Trop, recommencez.
  5. Vérifiez si tous les booléens du tableau sont vrais. Sinon, retournez à 3.
  6. Terminé.
1
Brendan Long

Randomsubsetsort.

Étant donné un tableau de n éléments, choisissez chaque élément avec la probabilité 1/n, randomisez ces éléments et vérifiez si le tableau est trié. Répéter jusqu'à trié.

Le temps attendu est laissé comme exercice au lecteur.

1
Steven Armstrong

Oui, SimpleSort, en théorie, il fonctionne dans O(-1), bien que ce soit équivalent à O(...9999) , ce qui équivaut à O (- 1), qui ça arrive est aussi équivalent à O (). Voici mon exemple d'implémentation:

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