洗牌算法Fisher–Yates shuffle

在有个函数int rand(int n)返回1-n之间的随机数。如何把数组A[N]打乱?

最初的Fisher–Yates算法是在另外开辟一个数组B[N],把打算后的A[N]放到B[N]中,步骤如下

设i=0

1、生成1-A.length长度之间的随机数k

2、把A[k]放到B[i],去除数组A中的A[k],i++。

3、如果A.length>0,转到第1步。

这个算法要去除A中的数,每次要移位,所以算法复杂度为O(N^2)。

例如一个算法过程如下:

随机数范围 随机数 A B  
  1 2 3 4 5 6 7 8 
随机数范围 随机数 A B
1–831 2 3 4 5 6 7 83
随机数范围 随机数 A B
1–741 2 3 4 5 6 7 83 5
随机数范围 随机数 A B
1–651 2 3 4 5 6 7 83 5 7
1–531 2 3 4 5 6 7 83 5 7 4
1–441 2 3 4 5 6 7 83 5 7 4 8
1–311 2 3 4 5 6 7 83 5 7 4 8 1
1–221 2 3 4 5 6 7 83 5 7 4 8 1 6
  1 2 3 4 5 6 7 83 5 7 4 8 1 6 2
后来算法有了改进,不是另外开辟数组,而是来交换数组A上面的元素来达到重排。

这个算法有2个版本,原理一样:

版本1:

for(int i = n; i>=1; --i)
{
	int j=rand(i);//生成1-i之间的随机数
	exchange(A[i],A[j]);//交换A[i],A[j]
}

版本2:

for(int i = 1; i <= n; ++i)
{
	int j=(rand(n)/n)*(n-i+1)+i-1;//生成i-n之间的随机数
	exchange(A[i],A[j]);//交换A[i],A[j]

版本1的一个演算过程如下:

随机数范围随机数AA(已排序部分)



随机数范围
随机数AA(已排序部分)
1–861 2 3 4 5 8 76

随机数范围 随机数 A A(已排序部分)
1–727 3 4 5 82 6
随机数范围 随机数 A A(已排序部分)
1–661 7 3 4 58 2 6
1–515 7 3 41 8 2 6
1–435 7 43 1 8 2 6
1–335 74 3 1 8 2 6
1–2175 4 3 1 8 2 6

参考:http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值