for(int i=suit.length-1;i>0;i--)
{
random1 = Random.next(1,i);
exchange(suit[random1],suit[i]);
}
为啥是这样呢?
一般会觉得合理的方案如下:
for(int i=0;i<suit.length;i++)
{
random1 = Random.next(1,n);
random2 = Random.next(1,n);
exchange(suit[random1],suit[random2]);
}
这个算法在设计上能够充满整个样本空间,确实存在n!种可能性,但是不够好。
为什么不够好呢,因为这种算法不能够【确保】照顾到每一张牌。
而Fisher–Yates算法在样本空间上,跟前面简单粗暴的随机抽取一样。充满了n!的样本空间,好在哪里呢?
因为它利用了抽卡本身的顺序,【保证照顾】到了每一张原本序列中的卡,而简单粗暴随机抽取存在出现重复位置的可能性,就等于浪费了一次排序的机会,换句话说,其等效抽卡次数因为出现了过去相同的洗法,有效洗牌次数下降,样本空间缩小,无法充满整个n!空间,所以有效性会下降。
而Fisher–Yates算法在原理上保证了不会出现浪费次数,重复选择的情况,导致样本空间一直保持n!,没有坍缩,这就是其在数学意义上优秀的原因。