现在的位置: 首页 > 综合 > 正文

概率算法 — 洗牌

2019年04月21日 ⁄ 综合 ⁄ 共 779字 ⁄ 字号 评论关闭

    遍历数组,遇到第i个元素时,产生一个i到n-1之间的随机数,然后两个位子的数互换。

 

 

void shuff(int *ap, int n)

{

    int i;

    for (i=0; i<n; i++)

    {

           int t = rand()%(n-i)+i;

           swap(a[i],a[t]);

    }

}

 

第一个元素所在的位置为ap+0,这个位置上,应该每个数字出现的概率均为1/n。第一次交换时,rand函数产生的数字范围就是0到n-1,因此确实每个数字都有可能换到ap+0这个地方。对于ap+1,数字出现的概率为: (n-1)/n * 1/(n-1)  =1/n     第一次没有被换到ap+0的概率   乘以  第二次被换到ap+1位置的概率。

 

因此,随机性是满足的~

 

 

 

 

PS:如果要求所有元素都不在开始的位置上,那就在产生随机位置的时候,除去自己的位置即可。

原本是从i到n-1选一个,现在从i+1到n-1中选一个就行了。

 

 

现在有N个位置,按照顺序排列,申请一个一维数组来存储。对于从0至N-1的树i,按照从小到大的顺序,利用随即数随机选取一个从i+1至N-1的数来与第i个数交换位置。这样利用线性时间就完成了操作,也不存在开寻址的问题,因为全部是交换操作。

下面来说明其中的三个问题:

1.每个数都不在自己原来的位置了。这是显然的,因为第i次交换时,如果这个位置上为i,则它会被换到后面去,由于之后不再进行对位置i的操作,所以,这个位置将不会再变化了;如果这个位置上不为i,则之间肯定被换到位置i之前了,那么再换过来的也肯定不会是i。

2.这个算法不会把结果限制在一个小区域内。这也是显然的,对于任意一种排列,实际上,如果我每次对序列的操作都选择排列上相应位置的数来交换就行了。

3.这个算法对生成任意满足条件的排列都是等概率的。这也是显然的。

抱歉!评论已关闭.