Skeet'in bu teklifinden başlayarak:
Sevdiğim bir karıştırma yöntemi değil, çoğunlukla O (n) n'in bir O (n) karıştırması kolay olduğunda iyi bir sebep olmadığı gerekçesiyle. Sorudaki kod, temel olarak her bir öğeye rastgele ( umarım benzersiz! ) Bir sayı vererek ve daha sonra öğeleri bu sayıya göre sıralayarak çalışır.
Umarım eşsiz olmasının nedenini biraz açıklayacağım !
Şimdi, gelen Enumerable.OrderBy :
Bu yöntem kararlı bir sıralama gerçekleştirir; yani, iki öğenin tuşları eşitse, öğelerin sırası korunur
Bu çok önemli! İki öğe aynı rastgele sayıyı "alırsa" ne olur? Dizide oldukları sırayla kalırlar. Şimdi, bunun gerçekleşme olasılığı nedir? Tam olarak hesaplamak zordur, ancak tam olarak bu problem olan Doğum Günü Sorunu vardır.
Şimdi, gerçek mi? Bu doğru mu?
Her zaman olduğu gibi, şüpheye düştüğünüzde, bazı program satırları yazın: http://pastebin.com/5CDnUxPG
Bu küçük kod bloğu, geriye doğru yapılan Fisher-Yates algoritmasını kullanarak 3 öğeden oluşan bir dizi belirli bir kez karıştırır, Fisher-Yates algoritması ileriye doğru yapılır ( wiki sayfasında iki sahte kod algoritması vardır ... Eşdeğer üretirler sonuçlar, ancak biri ilk öğeden son öğeye yapılırken diğeri son öğeden ilk öğeye yapılır), http://blog.codinghorror.com/the-danger-of-naivete/ ' nin naif yanlış algoritması ve .OrderBy(x => r.Next())
ve .OrderBy(x => r.Next(someValue))
.
Şimdi, Rastgele .
0'dan büyük veya 0'a eşit ve MaxValue'dan küçük bir 32 bit işaretli tam sayı.
bu yüzden
OrderBy(x => r.Next(int.MaxValue))
Bu sorunun var olup olmadığını test etmek için diziyi büyütebiliriz (çok yavaş bir şey) veya rastgele sayı üretecinin maksimum değerini azaltabiliriz ( int.MaxValue
"özel" bir sayı değildir ... Sadece çok büyük bir sayıdır). Sonunda, algoritma, kararlılığı ile önyargılı değilse OrderBy
, herhangi bir değer aralığı aynı sonucu vermelidir.
Program daha sonra 1 ... 4096 aralığında bazı değerleri test eder. Sonuçlara bakıldığında, düşük değerler (<128) için algoritmanın çok taraflı olduğu (% 4-8) oldukça açıktır. En az 3 değer ile ihtiyacınız var r.Next(1024)
. Diziyi büyütürseniz (4 veya 5), o zaman bile r.Next(1024)
yeterli değildir. Ben karıştırma ve matematik uzmanı değilim, ama dizi uzunluğunun her ekstra bit için, maksimum değerin 2 ekstra bit gerekir (çünkü doğum günü paradoks sqrt (rakamlar) bağlı olduğundan), bu yüzden maksimum değer 2 ^ 31 ise, dizileri 2 ^ 12/2 ^ 13 bite (4096-8192 öğe) kadar sıralayabilmeniz gerektiğini söyleyeceğim