Existe-t-il des algorithmes de tri pires que Bogosort (alias Monkey Sort)? [fermé]


180

Mes collègues m'ont ramené dans le temps à mes jours d'université avec une discussion sur les algorithmes de tri ce matin. Nous nous sommes souvenus de nos favoris comme StupidSort , et l'un de nous était sûr d'avoir vu un algorithme de tri qui l'était O(n!). Cela m'a amené à chercher les «pires» algorithmes de tri que j'ai pu trouver.

Nous avons postulé qu'un tri complètement aléatoire serait assez mauvais (c'est-à-dire randomiser les éléments - est-ce dans l'ordre? Non? Randomiser à nouveau), et j'ai regardé autour de moi et j'ai découvert que cela s'appelait apparemment BogoSort, ou Monkey Sort, ou parfois juste Random Sort .

Monkey Sort semble avoir les pires performances des cas O(∞), les meilleures performances des cas O(n)et les performances moyennes de O(n·n!).

Quel est l'algorithme de tri actuellement officiellement accepté avec la pire performance de tri moyenne (et donc pire que O(n·n!))?


10
Combien de bogomips par bogosort? Les esprits curieux veulent savoir.
zombat le

13
Pour clarifier, excluez-vous le cas trivial où la meilleure performance de cas est O (∞)?
tloflin


6
J'ai entendu dire que le genre de singe est aussi connu sous le nom de "genre d'homme ivre", un nom que je trouve beaucoup plus évocateur.
Matteo Italia

6
@Matteo Italia - ou cela pourrait être appelé "Tri pour tout-petits" comme toute personne de 2 ans peut en témoigner.
Martin Capodici

Réponses:


447

Extrait de la page Algorithmes ésotériques de David Morgan-Mar : Intelligent Design Sort

introduction

Le tri 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 d'origine soit dans l'ordre exact dans laquelle elle se trouve est de 1 / (n!). Il y a une si faible probabilité de cela qu'il est clairement absurde de dire que cela s'est produit par hasard, donc cela a dû être consciemment mis dans cet ordre par un trieur intelligent. Par conséquent, il est prudent de supposer qu'il est déjà trié de manière optimale d'une manière qui transcende notre compréhension mortelle naïve de "l'ordre ascendant". Toute tentative de changer cet ordre pour se conformer à nos propres idées préconçues le rendrait en fait moins trié.

Une 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 ne nécessite même aucun de ces trucs informatiques technologiques suspects. Félicitez le trieur!

Retour d'information

Gary Rogers écrit:

Rendre le tri constant dans le temps nie la puissance de The Sorter. Le trieur existe en dehors du temps, donc le tri est intemporel. Le fait de prendre du temps pour valider le tri diminue le rôle du trieur. Ainsi ... ce type particulier est imparfait et ne peut être attribué à «The Sorter».

Hérésie!


96
Aussi connu sous le nom de "Tri par hypothèse": Supposons que la liste soit triée, retournez!
BioGeek

42
+100 - cette réponse est faite à 100% de pure victoire.
womp

11
Hey! N'oubliez pas le «tri indécis» (également connu sous le nom de «tri de Schrodinger» ou «tri quantique»), où la liste peut ou non être triée, cependant la vérification révélera si oui ou non. Voici mon implémentation échantillon: 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
Nous devrions doubler ce tri Candide :"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
Pour ma part, je souhaite la bienvenue à notre nouveau maître du tri. Tous saluent le trieur!
Bryson

311

Il y a de nombreuses années, j'ai inventé (mais jamais implémenté) 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 aboutir à un tri réussi.

Pour plus de fiabilité, copiez la baie dans un emplacement blindé et comparez les baies potentiellement triées à l'original.

Alors, comment vérifier le tableau potentiellement trié par rapport à l'original? Vous triez simplement chaque tableau et vérifiez s'ils correspondent. MiracleSort est l'algorithme évident à utiliser pour cette étape.

EDIT: Strictement parlant, ce n'est pas un algorithme, car il n'est pas garanti de se terminer. Est-ce que "pas un algorithme" est qualifié de "pire algorithme"?


39
Je suppose que l'on peut utiliser des rayons cosmiques pour prouver l'exactitude de cet algorithme.
ghord

1
Quel est le grand O de cela? O(2^N)?
Mooing Duck

14
@MooingDuck: Je ne pense pas qu'il ait réellement un gros O.
Keith Thompson

5
@MooingDuck: Strictement parlant, si ça ne se termine pas, ce n'est pas un algorithme, d'après ce qu'ils m'ont appris à l'université et l'article de Wikipedia .
Keith Thompson

7
@Olathe: The Halting Problem dit que nous ne pouvons pas déterminer pour tous les programmes s'ils s'arrêtent, mais il existe de nombreux programmes pour lesquels nous pouvons prendre cette décision. Nous savons que Quicksort et Bubblesoft s'arrêtent, et nous savons que ce sont des algorithmes.
Keith Thompson

136

Bogosort quantique

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

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

A l'issue de l'algorithme, la liste sera triée dans le seul univers restant debout. Cet algorithme prend le temps O (N) du cas le plus défavorable et le temps O (1) du cas moyen. 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 chances qu'il soit détruit sur le troisième, et ainsi de suite.


43
Mais le temps cesse d'exister dans l'univers que vous venez de détruire. Ainsi, un observateur dans un univers que vous n'avez pas encore vérifié ne pourra pas dire dans quelle mesure l'algorithme a été exécuté. Ainsi, cet algorithme prend toujours O (1) temps, car les destructions d'univers précédentes n'existent plus.
Barry Brown

12
Oui, dans le seul univers qui observe la liste triée, il a fallu du temps à O (n) pour s'exécuter - combien de temps cela a pris dans d'autres univers n'a pas d'importance.
Nick Johnson

19
Cet algorithme pose cependant un problème beaucoup plus important. Supposons qu'une fois sur 10 milliards, vous conclurez par erreur qu'une liste est triée alors qu'elle ne l'est pas. Il y en a 20! façons de trier une liste de 20 éléments. Après le tri, les univers restants seront celui dans lequel la liste a été triée correctement, et les 2,4 millions d'univers dans lesquels l'algorithme a conclu par erreur la liste ont été triés correctement. Donc, ce que vous avez ici est un algorithme pour grossir massivement le taux d'erreur d'une machine.
Nick Johnson

10
C'est évidemment le meilleur algorithme de tri, pas le pire.
Boann

11
Le non-respect des conseils de Beetle peut entraîner la destruction de tous les univers.
CrashCodes

61

Je suis surpris que personne n'ait encore parlé de sleepsort ... Ou ne l'ai-je 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 3,5 mois pour trier 2 numéros est un peu mauvais.


3
Cela semble être une O(N)sorte, mais en vérité est limité par la manière dont le système d'exploitation implémente les minuteries.
Mooing Duck

7
Quelle que soit la façon dont vous le coupez, cela présente probablement une meilleure croissance que le bogosort.
Mooing Duck

8
J'y vois une condition de course.

5
Vous pouvez modifier le sleep "$1"en sleep "0.$(printf "%010d" $1)"pour améliorer sensiblement les performances. time ./sleepsort.sh 8864569 7puis s'exécute en 0,009 s sur mon ordinateur portable.
Sam Kellett

1
Cela fonctionne en complexité O (N) (dépendant bien sûr de l'implémentation de la minuterie), c'est un simple tri de seau sous une forme différente.
Qwerty01 du

61

Jingle Sort, comme décrit ici .

Vous donnez chaque valeur de votre liste à un enfant différent à Noël. Les enfants, qui sont des êtres humains terribles, compareront la valeur de leurs dons et se classeront en conséquence.


51

J'ai eu un conférencier qui a suggéré une fois de générer un tableau aléatoire, de vérifier s'il était trié, puis de vérifier si les données étaient les mêmes que le tableau à trier.

Meilleur cas O (N) (bébé pour la première fois!) Pire cas O (jamais)


4
Plus intéressant à analyser est le cas moyen , qui est ...?
Mooing Duck

5
Comme le disent tous les meilleurs manuels, cela reste un exercice pour le lecteur!
Daniel

43
Mooing Duck: O (parfois)
Ilya O.

1
@MooingDuck nous avons besoin de connaître la cardinalité du type d'élément et de la distribution utilisée pour générer des éléments aléatoires dans des tableaux aléatoires.
Afficher le nom

5
La complexité est O (N! * Z ^ N) où Z est la taille de l'ensemble des valeurs possibles et N est la longueur du tableau.
jakubiszon

30

Si vous gardez l'algorithme significatif de quelque manière que ce soit, O(n!)c'est la pire limite supérieure que vous puissiez atteindre.

Puisque la vérification de chaque possibilité pour une permutations d'un ensemble à trier prendra des n!mesures, vous ne pouvez pas être pire que cela.

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

list = someList
while (list not sorted):
    doNothing

14
Mais il faut O (n) pour vérifier s'il est trié, donc vous pouvez obtenir O (n * n!)
erikkallen

3
@erikkallen: Nous pouvons certainement proposer un algorithme pour vérifier le tri qui est pire que O (n). Par exemple, pour chaque élément du tableau, vérifiez qu'il est supérieur à tous les éléments précédents, tout comme le tri par insertion fonctionne. C'est un algorithme O (n ^ 2), et je suis sûr que je pourrais trouver pire en y réfléchissant un peu.
David Thornley

7
@David Thornley: l'algorithme de vérification suivant montrerait peut-être le même esprit que le bogosort: choisissez deux éléments aléatoires, vérifiez que celui avec le plus petit index est plus petit ou égal à celui avec le plus grand index, puis recommencez. Conservez une matrice de bits carrés pour voir quelles combinaisons ont déjà été vérifiées. Bien sûr, la vérification de cette matrice pourrait également se faire dans une marche aléatoire ...
Svante

23

Il existe une sorte de bogobogosort. Tout d'abord, il vérifie les 2 premiers éléments et les trie. Ensuite, il vérifie les 3 premiers, les bogosorte, et ainsi de suite.

Si la liste est dans le désordre à tout moment, elle redémarre en triant à nouveau les 2 premiers. Bogosort régulier a une complexité moyenne de O(N!), cet algorithme a une complexité moyenne deO(N!1!2!3!...N!)

Edit : Pour vous donner une idée de la taille de ce nombre, pour les 20éléments, cet algorithme prend en moyenne des 3.930093*10^158 années , bien au-dessus de la mort thermique proposée de l'univers (si cela se produit) d' 10^100 années ,

alors que le tri par fusion prend environ .0000004 quelques secondes , le tri par bulles en .0000016 secondes et bogosort prend des 308 années , des 139 jours , des 19 heures , des 35 minutes , des 22.306 secondes , en supposant qu'une année équivaut à 365,242 jours et qu'un ordinateur effectue 250 000 000 d'opérations entières 32 bits par seconde.

Edit2 : Cet algorithme n'est pas aussi lent que le tri miracle "algorithme", qui probablement, comme ce type, fera aspirer l'ordinateur dans le trou noir avant de réussir à trier 20 éléments, mais si c'était le cas, j'estimerais une complexité moyenne d' 2^(32(the number of bits in a 32 bit integer)*N)(the number of elements)*(a number <=10^40) années ,

puisque la gravité accélère le déplacement des puces alpha, et il y a 2 ^ N états, ce qui est 2^640*10^40, ou environ des 5.783*10^216.762162762 années , bien que si la liste commençait triée, sa complexité serait seulement O(N), plus rapide que le tri par fusion, qui n'est que N log N même dans le pire des cas.

Edit3 : Cet algorithme est en fait plus lent que le tri miracle car la taille devient très grande, disons 1000, puisque mon algorithme aurait une durée d'exécution de plusieurs 2.83*10^1175546 années , tandis que l'algorithme de tri miracle aurait une durée d'exécution de plusieurs 1.156*10^9657 années .


2
excellente réponse travaillée. triste il n'a pas de visibilité
swyx

21

Bogobogosort. Oui, c'est une chose. à Bogobogosort, vous Bogosort le premier élément. Vérifiez si cet élément est trié. Étant un élément, ce sera. Ensuite, vous ajoutez le deuxième élément et Bogosortez ces deux jusqu'à ce qu'il soit trié. Ensuite, vous ajoutez un autre élément, puis Bogosort. Continuez à ajouter des éléments et le tri par bogo jusqu'à ce que vous ayez enfin terminé chaque élément. Cela a été conçu pour ne jamais réussir avec une liste importante avant la mort de chaleur de l'univers.


5
Sainte mère de code. Je pense que nous pouvons même faire un court-métrage Bogolplex.
MrKekson

19

Vous devriez faire des recherches dans le domaine passionnant des algorithmes pessimaux et de l'analyse de simplexité . Ces auteurs travaillent sur le problème du développement d'un tri avec un meilleur cas pessimal (le meilleur cas de votre bogosort est Omega (n), tandis que le tri lent (voir l'article) a une complexité temporelle au meilleur cas non polynomiale).


16

Voici 2 sortes de choses que j'ai trouvées avec mon colocataire à l'université

1) Vérifiez l'ordre 2) Peut-être qu'un miracle s'est produit, passez à 1

et

1) vérifier si c'est en ordre, sinon 2) mettre chaque élément dans un paquet et le renvoyer sur un serveur distant vers vous. Certains de ces paquets reviendront dans un ordre différent, alors passez à 1


Le second est presque l'équivalent d'une sorte de bozo. Le premier est cependant intelligent.
Mooing Duck

1
Le premier est Miracle Sort.
Charles

14

Il y a toujours le Bogobogosort (Bogoception!). Il exécute Bogosort sur des sous-ensembles de plus en plus grands de la liste, puis recommence 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; }
}

5
J'aime l'idée que cet algorithme est conçu pour ne jamais se terminer "avant la mort par la chaleur de l'univers pour une liste
assez

10

1 Mettez vos objets à trier sur des fiches.
2 Jetez-les en l'air par temps venteux, à un mile de votre maison.
2 Jetez-les dans un feu de joie et confirmez qu'ils sont complètement détruits.
Vérifiez le sol de votre cuisine pour la commande correcte.
4 Répétez si ce n'est pas le bon ordre.

Le meilleur scénario de cas est O (∞)

Modifiez ci-dessus sur la base d'une observation astucieuse de KennyTM


9
Non, c'est pire car il n'y a aucune chance de réussir. Comment les fiches entreraient-elles dans votre cuisine? Ils soufflent dehors. Ça s'appelle, euh, maistheadsort.
Patrick Karcher

Je pense qu'il veut dire jeter les cartes en l'air à l' extérieur , puis vérifier votre sol à l' intérieur , où il n'y aura pas de cartes. Bien qu'il ne s'agisse pas d'un algorithme "nommé" ... c'est certainement pire!
womp

10
@Patrick Quantum tunneling.
kennytm

8
@KennyTM. Cela m'était réellement venu à l'esprit. Il y a une chance extrêmement faible mais non nulle qu'un objet puisse disparaître et réapparaître à tout autre point de l'univers. Je suppose que cela pourrait arriver à un millier de fiches. . . Oi. Dangit, mon algorithme est défectueux . Je le réparerai . . .
Patrick Karcher

3
C'est un peu comme prendre du thé et pas de thé en même temps. Ou voyager dans l'espace à l'aide d'un lecteur d'improbabilité infinie.
Barry Brown

9

Le "que voudriez-vous que ce soit?" Trier

  1. Notez l'heure du système.
  2. Trier en utilisant Quicksort (ou toute autre chose raisonnablement raisonnable), en omettant le tout dernier échange.
  3. Notez l'heure du système.
  4. Calculez le temps requis. L'arithmétique de précision étendue est une exigence.
  5. Attendez le temps requis.
  6. Effectuez le dernier échange.

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


8

Rien ne peut être pire que l'infini.


39
Infinity + 1. Jinx, aucun retour.
zombat

24
Pas pour des valeurs extrêmement grandes de 1;)
zombat

8
Ce qui me souffle vraiment sur le concept de l'infini, c'est que vous pouvez avoir différentes "tailles" d'infini. Par exemple, considérons l'ensemble de tous les nombres entiers - sa taille est infinie. Considérons maintenant l'ensemble de tous même entiers - il est aussi infini en taille, mais il est aussi bien la moitié de la taille de la première série. Les deux tailles infinies, mais différentes. Tellement génial. Le concept de «taille» ne fonctionne tout simplement pas dans le contexte de l'infini.
zombat

4
@zombat: Vous parlez de cardinalité, pas d'infini comme symbole indiquant une tendance sur la ligne réelle / le plan complexe.
kennytm

18
@zombat. La taille de l'ensemble des entiers pairs est la même que celle de l'ensemble des entiers, comme le montre le fait que vous pouvez les placer dans une correspondance biunivoque. Maintenant, il y a plus de nombres réels que d'entiers, comme l'a d'abord montré Cantor.
David Thornley

5

Le tri Bozo est un algorithme associé qui vérifie si la liste est triée et, sinon, échange deux éléments au hasard. Il a les mêmes performances dans les meilleurs et les pires cas, mais je m'attendrais intuitivement à ce que le cas moyen soit plus long que celui de Bogosort. Il est difficile de trouver (ou de produire) des données sur les performances de cet algorithme.


5

Segments de π

Supposons que π contienne toutes les combinaisons de nombres finis possibles. Voir la 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 de ce tableau, ajustez le décalage décimal π et recommencez.
  3. Vérifiez si le tableau réorganisé est trié. Si c'est le cas, ajustez le décalage et recommencez.

4

Une performance dans le pire des cas de O (∞) pourrait même ne pas en faire un algorithme selon certains .

Un algorithme n'est qu'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 qu'auparavant. On pourrait délibérément mettre la connaissance du nombre d'étapes prises dans l'algorithme et le faire se terminer et produire la sortie correcte seulement après que le Xnombre d'étapes ait été fait. Cela Xpourrait très bien être de l'ordre de O (n 2 ) ou O (n n! ) Ou tout ce que l'algorithme souhaite faire. Cela augmenterait effectivement ses limites de cas optimales ainsi que moyennes.

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


3

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 pire des cas est la complexité O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Un autre algorithme de tri lent est en fait nommé 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);
}

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


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

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

Double bogosort

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


1

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 le tableau que vous triez. Définissez-les tous sur faux.
  2. Exécuter une itération de bogosort
  3. Choisissez deux éléments aléatoires.
  4. Si les deux éléments sont triés l'un par rapport à l'autre (i <j && tableau [i] <tableau [j]), marquez les index des deux sur le tableau booléen sur true. Overwise, recommencez.
  5. Vérifiez si tous les booléens du tableau sont vrais. Sinon, revenez à 3.
  6. Terminé.

1

Oui, SimpleSort, en théorie, il fonctionne O(-1)mais cela équivaut àO(...9999) ce qui est à son tour équivalent à O (∞ - 1), ce qui est également é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

Un sur lequel je travaillais juste consiste à choisir deux points aléatoires, et s'ils sont dans le mauvais ordre, inverser toute la sous-plage entre eux. J'ai trouvé l'algorithme sur http://richardhartersworld.com/cri_d/cri/2001/badsort.html , qui dit que le cas moyen est 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 pourrait être possible de le faire plus efficacement, car je pense qu'il pourrait être possible de faire l'opération d'inversion dans le temps O (1).

En fait, je viens de réaliser que faire cela ferait tout ce que je dis peut-être parce que je viens de réaliser que la structure de données que j'avais à l'esprit mettrait l'accès aux éléments aléatoires en O (log n) et déterminerait s'il doit être inversé en O (n ).


1

Randomsubsetsort.

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

Le temps prévu est laissé comme exercice pour le lecteur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.