2012-01-14 12 views
11

klasik Fisher Yates şuna benzerFisher Yates varyasyon

void shuffle2(std::vector<int>& vec) 
{ 
    int n = vec.size(); 
    for (int i = 1; i < n; ++i) 
    { 
     std::swap(vec[i], vec[rand() % (i + 1)]); 
    } 
} 

hiçbir şekilde kötü bu versiyon mı (ya da ilkinden daha iyi)? Ortaya çıkan olasılıkları çarpıyor mu?

+0

"Daha kötüsü", "eşit olmayan bir dağılımın üretilmesi" anlamına gelir, değil mi? –

+0

@ R.MartinhoFernandes: Sağ. “Ortaya çıkan olasılıkları çarpıyor mu?” – fredoverflow

+0

Daha çok matematik sorusu gibi. - Bir programlama sorusu olarak, neden bu işlevi C++ uygulamasında uyguluyorsunuz? Standart kütüphanede (random_shuffle). – UncleBens

cevap

3

Evet, bu bile rand() olduğunu varsayarak dağılım olduğunu. Her bir girdinin her bir permütasyonun eşit olasılıkla üretilebileceğini göstererek bunu ispatlayacağız.

N = 2 kolayca kanıtlanabilir. Çocukları, virgülle karakterleri en soldaki dizeye ekleyerek alabileceğiniz her dizeyi temsil eden bir ağaç olarak çizelim.

0,1 //input where 0,1 represent indices 
01 10 //output. Represents permutations of 01. It is clear that each one has equal probability 

N için, N-1 için her permütasyon olacak ve rastgele bile dağılımına sahip olmanın Bu boktan indüksiyon yöneltmelidir N

(N-1 0th permutation),N  .....   (N-1 Ith permutation),N ________________________ 
    /   \      /     \        \ 
0th permutation of N 1st permutation.... (I*N)th permutation ((I*N)+1)th permutation .... (I*N)+(I-1)th permutation 

için son karakteri takas.


Örnek:

N = 2:

0,1 
01 10 // these are the permutations. Each one has equal probability 

K = 3:

  0,1|2   // the | is used to separate characters that we will insert later 
    01,2   10,2 // 01, 10 are permutations from N-1, 2 is the new value 
210 021 012 201 120 102 // these are the permutations, still equal probability 

N = 4:

              0,1|23 

                 01,2|3 10,2|3 

              012,3 021,3 210,3 102,3 120,3 201,3 


            1203 1230 1302 3201 
             2103 2130 2301 3102 1023 1032 1320 3021 
(okuma yardım etmek için bir eğim)

etc

1

Bana iyi görünüyor (rand()% N'nin tarafsız olmadığını varsayarak). Görünüşe göre, her bir girdi permütasyonu, her rastgele seçimin dengelendiği, tam olarak 1 rastgele seçenek dizisi tarafından üretildiğini kanıtlamak mümkün olmalıdır.

sen n üretmek için n eşit olasılıkla yolları n olduğunu görebilirsiniz böyle

İşte
for (int i = 0; i < v.size(); ++i) { 
    swap(v[i], v[rand() % v.size()]); 
} 

olarak, hatalı bir uygulama ile bu karşılaştırın! permütasyonlar ve n n'dan beri n! tarafından bölünemez. n> 2, bu permütasyonların bazıları diğerlerinden daha sık üretilmelidir.

İlgili konular