关于洗牌算法,网上有比较多的实现,一个比较简单直接的实现如下:
void ShuffleArray_Fisher_Yates(char* arr, int len)
{
int i = len, j;
char temp;
if ( i == 0 ) return;
while ( --i ) {
j = rand() % (i+1);
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
对这段代码简单分析,我们以52张牌为例,分别编号为0到51,经过一轮洗牌之后,第n张牌最终停留在n位置的概率应该是1/52。根据算法,我们逐一分析:
对于第51张牌,很明显停留在51位置的概率是1/52;
对于第50张牌,在上一轮交换中,它不能被换到第51位置,概率为51/52,这一轮它需要停留在50位置,因此,概率为1/51,所以总的概率为1/52;
对于第49张牌,在第一轮中,它不能被交换到51位置,概率51/52,第二轮不能交换到50,概率50/51,第三轮,概率1/50,所以总的概率 51/52×50/51×1/50 = 1/52;
以此类推,可以得出 每一张牌停留在原始位置的概率都是1/52;
当然,也可以说经过一次洗牌之后,停留在第n个位置上的牌的编号为m的概率为1/52;
由于random算法并不是真随机数,因此所得到的概率并不完全符合1/52;
如果要严格证明,需要证明出现任何一种排列的时候,其概率为1/n!;