Bogosort(別名Monkey Sort)よりも悪いソートアルゴリズムはありますか?[閉まっている]


178

今朝、同僚が大学時代に振り返って、ソートアルゴリズムについて話し合いました。StupidSortのようなお気に入りについて思い出しましたが、私たちの1人は、このような並べ替えアルゴリズムを見たことがあると確信していましたO(n!)。そのため、見つけた「最悪の」ソートアルゴリズムを探し始めました。

完全にランダムな並べ替えはかなり悪いと仮定しました(つまり、要素をランダム化します- 順序付けですか?いいえ?もう一度ランダム化します)。。

Monkey Sortは、最悪の場合のパフォーマンスO(∞)、最良の場合のパフォーマンスO(n)、および平均のパフォーマンスがであるようO(n·n!)です。

最悪の平均並べ替えパフォーマンスを備えた、現在公式に受け入れられている並べ替えアルゴリズムは何O(n·n!)ですか?


10
ボゴソートあたりのボゴミップはいくつですか?探究心は知りたいです。
zombat 2010

13
明確にするために、最高のパフォーマンスがO(∞)である些細なケースを除外していますか?
tloflin 2010


6
サルの種類は「酔った男の種類」とも呼ばれていると聞きました。
Matteo Italia

6
@Matteo Italia-または、2歳の人なら誰でも証明できるように、「Toddler Sort」と呼ぶこともできます。
Martin Capodici 2014年

回答:


442

デビッド・モーガン- 3月の密教アルゴリズムのページ:インテリジェントデザインソート

前書き

インテリジェントデザインソートは、インテリジェントデザインの理論に基づくソートアルゴリズムです。

アルゴリズムの説明

元の入力リストが正確な順序である確率は、1 /(n!)です。これが起こる可能性は非常に低いため、これが偶然に起こったと言うのは明らかにばかげているので、インテリジェントなソーターによってこの順序で意識的に行われたに違いありません。したがって、「昇順」についての私たちのナイーブな人間の理解を超越する何らかの方法ですでに最適にソートされていると想定しても安全です。私たち自身の先入観に準拠するようにその順序を変更しようとすると、実際にはソートが少なくなります。

分析

このアルゴリズムは時間的に一定であり、リストをインプレースでソートするため、追加のメモリはまったく必要ありません。実際、疑わしい技術的なコンピュータのようなものを必要としません。ソーターを称賛してください!

フィードバック

ゲイリーロジャースは書いています:

時間内にソートを一定にすることは、ソーターの能力を否定します。ソーターは時間外に存在するため、ソートは時代を超越しています。並べ替えの検証に時間がかかると、並べ替え機能の役割が失われます。したがって、この特定のソートには欠陥があり、「The Sorter」に起因するものではありません。

異端!


94
「仮定の並べ替え」とも呼ばれます。リストが並べ替え済みであると想定して、戻ります!
BioGeek 2010

42
+100-この答えは100%純粋な勝利から作られます。
2010

11
おい!リストがソートされる場合とされない場合がある「決定的ソート」(「シュレディンガーのソート」または「量子ソート」とも呼ばれます)を忘れないでください。ただし、リストをソートすると、ソートされているかどうかがわかります。これが私のサンプル実装です: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
この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
私は、一つには、私たちの新しい仕分け君主を歓迎します。ソーターを歓迎します!
ブライソン2014年

299

何年も前に、私は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

最終的に、メモリチップのビットを反転するアルファ粒子は、ソートを成功させるはずです。

信頼性を高めるには、アレイをシールドされた場所にコピーし、並べ替えられた可能性のあるアレイを元のアレイに対してチェックします。

では、ソートされた可能性のある配列を元の配列に対してどのようにチェックしますか?各配列を並べ替えて、それらが一致するかどうかを確認するだけです。MiracleSortは、このステップで使用する明白なアルゴリズムです。

編集:厳密に言えば、終了することが保証されていないため、これはアルゴリズムではありません。「アルゴリズムではない」は「悪いアルゴリズム」とみなされますか?


39
私は、このアルゴリズムの正当性を証明するために宇宙線を使用できると思います。
ghord

1
これの大きなOは何ですか? O(2^N)
Mooing Duck

12
@MooingDuck:大きなOは実際にはないと思います。–
Keith Thompson

5
@MooingDuck:彼らが大学で私に教えたこととウィキペディアの記事の両方によれば、厳密に言えば、それが終了しない場合、それはアルゴリズムではありません。
キース・トンプソン

7
@Olathe:停止問題は、すべてのプログラムが停止するかどうかを判断することはできないと述べていますが、その判断ができるプログラムはたくさんあります。私たち QuicksortとBubblesoftの停止を知っており、それらはアルゴリズムであることを知っています。
キーストンプソン

133

量子ボゴソート

量子力学の多世界解釈が正しいと想定する並べ替えアルゴリズム:

  1. リストがソートされていることを確認してください。そうでない場合は、宇宙を破壊します。

アルゴリズムの最後に、リストは残っている唯一の宇宙でソートされます。このアルゴリズムは、最悪の場合のO(N)および平均の場合のO(1)時間を使用します。実際、実行される比較の平均数は2です。2番目の要素で宇宙が破壊される可能性は50%で、3番目の要素で宇宙が破壊される可能性は25%などです。


42
しかし、あなたが破壊したばかりの宇宙には時間が存在しなくなります。したがって、まだ確認していないユニバースのオブザーバーは、アルゴリズムの実行量を知ることができません。したがって、以前の宇宙破壊は存在しないため、このアルゴリズムは常にO(1)時間かかります。
バリーブラウン

12
はい、ソートされたリストを監視する唯一のユニバースでは、実行にO(n)時間かかりました。他のユニバースでどれだけ時間がかかったかは関係ありません。
ニックジョンソン

19
ただし、このアルゴリズムにははるかに大きな問題があります。100億回に1回は、リストがソートされていない場合にリストがソートされていると誤って結論付けると想定します。20個あります!20要素のリストを並べ替える方法。ソート後、残りのユニバースはリストが正しくソートされたものになり、アルゴリズムが誤ってリストを結論付けた240万のユニバースは正しくソートされました。つまり、ここにあるのは、機械のエラー率を大幅に拡大するアルゴリズムです。
Nick Johnson

10
これは明らかに最悪の並べ替えアルゴリズムであり、最悪ではありません。
Boann、2012年

11
ビートルの助言を怠ると、すべての宇宙が破壊される可能性があります。
CrashCodes 2014年

60

誰もスリープソートについて言及していないことに驚いています...それとも気づいていませんか?とにかく:

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

使用例:

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

パフォーマンスの面ではひどいです(特に2番目の例)。2つの数値を並べ替えるのに約3.5か月待つのは少し悪いです。


3
これは一種のように見えますO(N)が、実際にはOSがタイマーを実装することによって制約されています。
Mooing Duck

7
どのようにカットしても、これはおそらくbogosortよりも優れた成長を示しています。
Mooing Duck

8
そこに競合状態が見られます。

5
を変更sleep "$1"sleep "0.$(printf "%010d" $1)"て、パフォーマンスを大幅に向上させることができます。time ./sleepsort.sh 8864569 7その後、私のラップトップでは0.009秒で実行されます。
Sam Kellett 2014年

1
これはO(N)の複雑さで実行されます(もちろん、タイマーの実装に依存します)。これは、異なる形式の単純なバケットソートです。
Qwerty01 2014年

60

ここで説明するジングルソート。

クリスマスには、リストの各値を別の子供に渡します。ひどい人間である子供たちは、贈り物の価値を比較し、それに応じて自分自身を分類します。


50

私はかつてランダム配列を生成し、それがソートされているかどうかを確認し、次にデータがソートされる配列と同じであるかどうかを確認することを提案した講師がいました。

最高のケースO(N)(初めての赤ちゃん!)最悪のケースO(なし)


4
分析するのがより興味深いのは、平均的なケース、つまり...?
Mooing Duck

4
すべての最高の教科書が言うように、これは読者のための練習問題として残されています!
Daniel

40
Mooing Duck:O(ときどき)
Ilya O.

1
@MooingDuckは、ランダムな配列でランダムな要素を生成するために使用される要素タイプと分布の基数を知る必要があります。
表示名

5
複雑さはO(N!* Z ^ N)で、Zは可能な値のセットのサイズ、Nは配列の長さです。
ジャクビゾン2014年

30

アルゴリズムを何らかの意味で意味のあるものに保つと、O(n!)は達成できる最悪の上限になります。

ソートするセットの順列の各可能性をチェックすることはn!ステップを踏むため、それ以上悪化することはありません。

それよりも多くのステップを実行している場合、アルゴリズムには実際に役立つ目的はありません。以下の単純なソートアルゴリズムは言うまでもありませんO(infinity)

list = someList
while (list not sorted):
    doNothing

14
しかし、並べ替えられているかどうかを確認するにはO(n)が必要なので、O(n * n!)を取得できます
erikkallen

3
@erikkallen:確かに、O(n)よりも悪いソートを検証するアルゴリズムを考え出すことができます。たとえば、配列の各要素について、挿入ソートが機能するように、それが以前のすべての要素よりも大きいことを確認します。これはO(n ^ 2)アルゴリズムであり、少し考えれば、さらに悪い結果になる可能性があります。
David Thornley、2010

7
@David Thornley:次のチェックアルゴリズムはおそらくbogosortと同じ精神を示します:2つのランダムな要素を選び、インデックスが小さい方がインデックスが大きい方と同じか小さいかを確認してから繰り返します。正方形のビット行列を保持して、どの組み合わせが既にチェックされているかを確認します。もちろん、この行列のチェックは、ランダムウォークで行うこともできます...
Svante 2010

19

ボゴボゴソート。はい、それは事です。Bogobogosortにとって、最初の要素はBogosortです。1つの要素が並べ替えられているかどうかを確認します。一つの要素である、それはなります。次に、2番目の要素を追加し、並べ替えられるまでこれら2つをBogosortします。次に、もう1つの要素を追加し、次にBogosortを追加します。最終的にすべての要素が完了するまで、要素の追加とBogosortingを続けます。これは、宇宙の熱死の前にかなりの数のリストで成功することは決してないように設計されました。


5
コードの聖母。ボゴルプレックスのショートもできると思います。
MrKekson 2015年

19

ペシマルアルゴリズムとシンプレキシティ分析のエキサイティングな分野について調査する必要があります。これらの著者は、悲観的なベストケースでソートを開発する問題に取り組んでいます(ボゴソートのベストケースはOmega(n)ですが、スローソート(論文参照)は非多項式のベストケースの時間複雑さを持っています)。


19

bogobogosortと呼ばれる種類があります。まず、最初の2つの要素をチェックし、それらをbogosortsします。次に最初の3をチェックし、それらをbogosortsします。

リストが順不同である場合は、最初の2つを再度bogosortすることから再開します。通常のボゴソートの平均複雑度はO(N!)、このアルゴリズムの平均複雑度はO(N!1!2!3!...N!)

編集:あなたにこの数がどのように大規模のアイデアを与えるために、のため20の要素、このアルゴリズムは、平均取る3.930093*10^158 の(それが発生した場合)だけでなく、宇宙の提案熱死の上、10^100

マージソートの周りに取るのに対し、.0000004 、バブルソート.0000016 、およびボゴソートはとり308 139 19 時間35 22.306 秒を年は365.242日であると仮定すると、コンピュータは毎秒250,000,000 32ビットの整数演算を行います。

Edit2:このアルゴリズムは、「アルゴリズム」ミラクルソートほど低速ではありません。おそらく、このソートのように、20個の要素を正常にソートする前に、コンピューターがブラックホールに吸い込まれることになります。2^(32(the number of bits in a 32 bit integer)*N)(the number of elements)*(a number <=10^40)

重力はチップのアルファ移動を高速化し、2 ^ N状態、つまり2^640*10^40、または約5.783*10^216.762162762 があるので、リストがソートされた状態で開始された場合、その複雑さはO(N)マージソートよりも速く、NログNであっても最悪の場合。

Edit3:このアルゴリズムは実際にミラクルソートよりも遅くなります。これは、サイズが非常に大きくなる(1000など)ためです。これは、私のアルゴリズムの実行時間が2.83*10^1175546 数年で、ミラクルソートアルゴリズムの実行時間が1.156*10^9657 数年になるためです。


1
すばらしい答え。悲しいことに、可視性がない
swyx 2017

16

ここに私が大学でルームメイトを思いついた2種類があります

1)注文を確認する2)多分奇跡が起こった、1に行く

そして

1)順序が正しいかどうかを確認し、そうでない場合は2)各要素をパケットに入れて、遠くのサーバーから跳ね返して自分自身に戻します。これらのパケットの一部は異なる順序で返されるため、1に進みます。


2つ目は、ボゾソートとほぼ同じです。最初は賢いですが。
Mooing Duck

1
最初はミラクルソートです。
Charles

14

常にBogobogosort(Bogoception!)があります。リストのますます大きなサブセットに対してBogosortを実行し、リストがソートされていない場合は最初からやり直します。

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
私は、このアルゴリズムが「どんなに大きなリストでも宇宙の熱死の前に」決して終わらないように設計されているという考えが好きです
A.Grandt

10

1ソートするアイテムをインデックスカードに入れます
。2家から1マイル離れた風の強い日に、アイテムを空中に投げます。
2それらをたき火に投げ入れ、完全に破壊されることを確認します。
3キッチンの床で正しい順序を確認します。
4正しい順序でない場合は繰り返します。

ベストケースのシーンリオはO(∞)

KennyTMによる鋭い観察に基づいて上記を編集します。


9
いいえ、成功する可能性がないため、これはさらに悪いことです。インデックスカードはどのようにあなたの台所に入りますか?彼らは外を吹いています。それは、ええと、バットヘッドソートと呼ばれています。
Patrick Karcher

私は彼がカードをの空中に投げて、それからカードがないことが保証されている内部のあなたの床チェックすることを意味すると思います。「名前付き」アルゴリズムではありませんが...それは確かに悪いです!
2010

10
@Patrick Quantumトンネリング。
kennytm

8
@KennyTM。それは実際に私に起こりました。 非常に小さいがゼロではない可能性があり、オブジェクトが消えて、宇宙の他の場所に再び現れる可能性があります。 私はそれ 1000枚のインデックスカードに起こる可能性があると思います。。。おい。Dangit、私のアルゴリズムには欠陥があります。直します。。。
Patrick Karcher、2010

3
お茶とお茶を同時に飲むようなものです。または、無限の確率ドライブを使用した宇宙旅行。
バリーブラウン

9

「何になりたいですか?」ソート

  1. システム時刻に注意してください。
  2. 最後のスワップを省略して、Quicksort(または合理的に理にかなった何か)を使用してソートします。
  3. システム時刻に注意してください。
  4. 必要な時間を計算します。拡張精度演算が必要です。
  5. 必要な時間待ちます。
  6. 最後のスワップを実行します。

考えられる限りの無限大ではないO(x)値を実装できるだけでなく、所要時間は間違いなく正しいです(それだけ長く待つことができる場合)。


8

無限よりも悪いことはありません。


38
インフィニティ+ 1. Jinx、ノーリターン。
zombat

24
1の非常に大きな値ではありません;)
zombat 2010

8
無限の概念について本当に私の心を打っているのは、無限の異なる「サイズ」を持つことができるということです。たとえば、すべての整数のセットを考えてみます。サイズは無限です。次に、すべての偶数の整数のセットを考えます。サイズも無限ですが、明らかに最初のセットの半分のサイズです。無限ですが、サイズは異なります。非常にすばらしい。「サイズ」の概念は、無限のコンテキストでは機能しません。
zombat 2010

4
@zombat:あなたは、カーディナリティーについて話しているのであって、実数線/複素平面上のトレンドを示す記号としての無限ではありません。
kennytm 2010

18
@zombat。偶数の整数のセットのサイズは、整数のセットのサイズと同じです。これは、整数を1対1で対応させることができるという事実によって示されています。現在、Cantorが最初に示したように、整数よりも実数が多くなっています。
David Thornley

5

Bozoソートは、リストがソートされているかどうかをチェックし、ソートされていない場合は、2つのアイテムをランダムに交換する関連アルゴリズムです。最高と最悪のケースのパフォーマンスは同じですが、平均的なケースはBogosortよりも長くなると直感的に予想します。このアルゴリズムのパフォーマンスに関するデータを見つける(または生成する)のは困難です。


5

πのセグメント

πにはすべての可能な有限数の組み合わせが含まれていると仮定します。math.stackexchangeの質問を参照してください

  1. 配列のサイズから必要な桁数を決定します。
  2. 配列の並べ替え方法を決定するために、π桁のセグメントをインデックスとして使用します。セグメントがこの配列のサイズ境界を超える場合は、π10進オフセットを調整してやり直してください。
  3. 並べ替えられた配列が並べ替えられているかどうかを確認します。ウートの場合は、オフセットを調整してやり直してください。

4

O(∞)の最悪の場合のパフォーマンスでは、いくつかのに基づくアルゴリズムになることすらありません。

アルゴリズムは単なる一連のステップであり、少し微調整することにより、以前よりも多くのステップで目的の出力を得ることができるため、常に状況を悪化させることができます。意図的にアルゴリズムに取り入れたステップ数の知識を入れて、アルゴリズムを終了させ、Xステップ数が完了した後でのみ正しい出力を生成することができます。それXは、O(n 2)やO(n n!)のオーダー、またはアルゴリズムが望むものなら何でも可能です。これにより、最良のケースと平均的なケースの範囲が効果的に増加します。

しかし、最悪のシナリオを突破することはできません:)


3

私のお気に入りの低速ソートアルゴリズムは、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(n^(log(3) / log(1.5))) = O(n^2.7095...)です。

別の低速ソートアルゴリズムは、実際には低速ソートと呼ばれています!

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

これO(n ^ (log n))は最良のケースを取ります... 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

このページは、トピックに関する興味深い読み物です:http : //home.tiac.net/~cri_d/cri/2001/badsort.html

私の個人的なお気に入りはトム・ダフの愚かなものです:

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


1

「ソート済み」ステップをランダムに実行することで、ソートアルゴリズムを遅くすることができます。何かのようなもの:

  1. 並べ替える配列と同じサイズのブール値の配列を作成します。それらをすべてfalseに設定します。
  2. bogosortのイテレーションを実行する
  3. 2つのランダムな要素を選択します。
  4. 2つの要素が互いに関連してソートされている場合(i <j && array [i] <array [j])、ブール配列の両方のインデックスをtrueにマークします。過剰に、最初からやり直してください。
  5. 配列内のすべてのブール値がtrueかどうかを確認します。そうでない場合は、3に戻ります。
  6. できました。

1

はい、SimpleSortは、理論的にはそれが実行されますO(-1)が、これがあると同等O(...9999)、それが起こるようにもO(∞)に相当し、 - O(1∞)へのターンと等価です。これが私のサンプル実装です:

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

1

私が今取り組んでいるのは、2つのランダムな点を選択することです。それらが間違った順序である場合は、それらの間の部分範囲全体を逆にします。アルゴリズムはhttp://richardhartersworld.com/cri_d/cri/2001/badsort.htmlで見つかりました。これは、平均的なケースはおそらくO(n ^ 3)またはO(n ^ 2 log n)のどこかにあることを示しています(彼は本当にわかりません)。

O(1)時間で反転操作ができるのではないかと思うので、もっと効率的にできると思います。

実際、私が考えているデータ構造がO(log n)のランダム要素にアクセスし、O(n )。


1

Randomsubsetsort。

n個の要素の配列を指定して、確率1 / nで各要素を選択し、これらの要素をランダム化して、配列がソートされているかどうかを確認します。ソートされるまで繰り返します。

予想される時間は、読者の練習問題として残されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.