随机排序的长序列

时间:2015-11-24 20:27:13

标签: c# random long-integer

从两个数据类型都是long的开始和结束开始,我想用它们生成一个随机排序的列表。

目前,我正在使用for循环填充列表:

for (var i = idStart; i < idEnd; i++){ list.Add(i); }

然后我使用扩展方法对列表进行随机播放。但是,当start和end之间的差异很大(数百万)时,for循环会导致内存不足异常。

是否有更高效,更时尚的方法来生成随机排序的long列表,其中每个数字只出现一次?

1 个答案:

答案 0 :(得分:5)

  

是否有更高效,更时尚的方法来生成随机排序的长列表,其中每个数字只出现一次?

是的,如果你消除了序列真正随机的要求。使用以下技术。

不失一般性,让我们假设您希望为某些n生成从0到n-1的数字。显然,你可以看到如何在x和y之间生成数字;只需生成从0到x-y的数字,然后将x添加到每个数字。

找到一个随机生成的数字z,它是n的互质。这样做是留给读者的练习。如果数量非常大,那么它将有所帮助;如果z是小模数,则很容易注意到该模式。

找到一个随机生成的数字m,介于0和n-1之间。

现在生成序列(m)* z%n,(m + 1)* z%n,(m + 2)* z%n,依此类推。该序列在(m + n)* z%n处重复;在此之前不再重复。再次,确定它不重复的原因留作练习。

很容易看出这不是真正的混乱,因为生成的序列少于n平方,而不是真正的随机抽样可能的n因子序列。但它可能足以满足您的目的;如果你使用类似System.Random之类的东西进行随机化,你就已经放弃了真正的洗牌。

我还注意到许多评论表明大量分配应该没有问题。这些注释忘记了(1)相关度量不是框中的RAM数量,而是最大连续用户模式地址空间块的大小,并且可以轻松地小于一亿个字节32位进程,(2)列表数据结构有意过度分配,(3)当列表满了时,必须分配底层数组的副本,将旧列表复制到新列表中,超过双倍临时列表的实际内存负载,以及(4)天真地尝试分配一亿字节结构的用户可能会尝试在整个程序中分配十几个这样的内容。你应该总是避免这么大的分配;如果您的数据结构需要大量存储,则将它们放在磁盘上。