也谈生成不重复的随机数系列(洗牌算法)

Posted by 翡翠小屋 on May 10, 2010

偶尔看到有人在讨论如何生成不重复的随机数系列(洗牌算法),发现他们用的方法复杂度十分高,要抛大量的随机数,因此把我以前用的洗牌算法也拿出来秀秀。

假设需要生成 1~54 的随机数,那么把 1~54 放入“数组”,抛 0~53 的随机数,把指定序号的牌,和最后一张牌交换。

下一步,抛 0~52 的随机数……

重复 53 次就可以洗完牌,只需要53个随机数,53次交换,复杂度相当低,可以在常数时间内完成。

演示代码如下:


int main()
{
	srand((unsigned int)time(NULL));
	const int count = 54;
	int cards[count];
	// 初始化未洗牌数组
	for (int i = 0; i < count; ++i)
		cards[i] = i + 1;
	for (int i = count; i > 0; --i) {
		int index = rand() % i;

		// 交换随机位置和最后未交换过的牌
		int x = cards[index];
		cards[index] = cards[i - 1];	
		cards[i - 1] = x;
	}
	std::copy(cards, cards+count, std::ostream_iterator<int>(std::cout, " "));
	return 0;
}