他の回答に加えて、これは遅すぎるため、単純なフィッシャー・イェイツのシャッフルよりも悪いです。 qsortアルゴリズムはO(n * log(n))、Fisher-YatesはO(n)です。
いくつかの詳細は、「シャッフル」のこの種は、一般的に働くだけでなく、the Fisher-Yates methodしない理由についてウィキペディアで提供されています:
他のシャッフル のアルゴリズムとの比較
フィッシャーイエーツshuffleがありますかなり 効率的です。確かに、その漸近時間 と空間の複雑さが最適です。 高品質の非公開 乱数ソースと組み合わせると、 も保証されています。 の結果が保証されています。いくつかの他の ソリューションに比べて、それはまた、得られた 順列の一部のみが必要な場合、それは、必要に応じて増分順列 を生成 を が途中で停止し、あるいは を停止して繰り返し再起動することができる、という利点 を有します。ハイレベルで高速 と プログラミング言語はビルトインアルゴリズムをソート、各要素セットの をシャッフルする 代替方法は、 乱数を割り当てられ、セットは、その後 これらの数に応じてソートされ 漸近的時間の複雑さ(O(n log n) 対O(n))が悪化しているにもかかわらず、実際にはより速くなる可能性がある[引用 が必要]。 Fisher-Yates シャッフルのように、正しく が実装されていれば、 の偏りのない結果も生成され、ランダムな の数字にバイアスのある種の が許容される可能性があります。ただし、 番号が重複しないように注意する必要があります。 ソートアルゴリズムは一般的に タイの場合には 要素をランダムに並べ替えないため、 を割り当てる必要があります。 ユーザー指定の比較関数でソートサポート言語 の一部の使用を見ている上記方法 の変異体は ランダムな値を返す 比較関数でそれをソートしてリストをシャッフルする あります。しかし、これは は常に動作しません。多くの場合、ソートアルゴリズムである が使用されており、 の結果は の内部で の実装で非対称になります。
この
は
hereにリンク:
ちょうどもう一つのことを私は方法の様々な バージョンで実験し、元のバージョン に 1つのより多くの欠陥を発見し、この 記事を書いている間(私が名前を変更〜shuffle_sort
)。私が言ったとき、私は 間違っていた「それがうまく シャッフル配列にそれが と呼ばれるたびに返されます。」
結果がうまく すべてでシャッフルされていません。彼らは偏っている。ひどく。それは、 は、要素のいくつかの順列(すなわち、 の順序)が他のものより である可能性が高いことを意味します。ここで再び ニュースグループの議論から借り、それを証明する コードの別のスニペットは、です:
N = 100000
A = %w(a b c)
Score = Hash.new { |h, k| h[k] = 0 }
N.times do
sorted = A.shuffle
Score[sorted.join("")] += 1
end
Score.keys.sort.each do |key|
puts "#{key}: #{Score[key]}"
end
3つの 要素のこのコード シャッフル10万回の配列:A、B、Cおよびレコードがどのように多くの 回のそれぞれの可能な結果は に達しました。この場合は、 の6つの発注があり、 はそれぞれ約16666.66回になるはずです。 なら、私たちはshuffle
(shuffle
またはshuffle_sort_by
)の公平なバージョンを試してみてください予想通り、 結果は以下のとおりです。もちろん
abc: 16517
acb: 16893
bac: 16584
bca: 16568
cab: 16476
cba: 16962
、いくつかの偏差が があるが、彼らは 超えるべきではありません の数パーセントは期待値であり、このコードを実行するたびに異なる である必要があります。 分布は であると言えます。
OKshuffle_sortメソッドを使用するとどうなりますか?
abc: 44278
acb: 7462
bac: 7538
bca: 3710
cab: 3698
cba: 33314
これは、すべての均一な分布 ではありません。再び?
これは、ソート方法がどのように偏っているかを示しており、これがなぜそうであるかを詳しく説明しています。最後に彼はCoding Horrorにリンク:
のが正しい クヌース・フィッシャーイエーツシャッフルアルゴリズムを見てみましょう。
for (int i = cards.Length - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
Swap(ref cards[i], ref cards[n]);
}
あなたは違いを参照していますか?私は 初めてそれを逃した。
Naïve shuffle Knuth-Fisher-Yates shuffle
rand.Next(3); rand.Next(3);
rand.Next(3); rand.Next(2);
rand.Next(3);
素朴なシャッフル3^3で 結果(27)の可能なデッキ 組み合わせ:3カードデッキのためのスワップ の比較。それは 数学は実際には があることを私たちに教えてくれるので、奇妙です!または可能な6つのカードデッキの の組み合わせ。 KFYシャッフルでは、最初に の注文から始めて、3番目のカードと交換してから、 の残りの2枚のカードをもう一度 と交換します。
変更が悪化しました。アリティ。 – Juliano
私はあなたが平等のためにどちらか一方を自由に選んだと思った... – ojblass