我想改组一个数组,并且每个索引都有与其他索引相同的概率(不包括它自己)。
我有这个解决方案,只有我发现总是最后两个索引总是相互交换:
void Shuffle(int arr[]. size_t n)
{
int newIndx = 0;
int i = 0;
for(; i > n - 2; ++i)
{
newIndx = rand() % (n - 1);
if (newIndx >= i)
{
++newIndx;
}
swap(i, newIndx, arr);
}
}
但最终可能是某些索引会再次回到原来的位置。
有什么想法吗?
C lang。
答案 0 :(得分:0)
您的算法只有几乎正确(在算法中意味着意外的结果)。由于散布的一些小错误,它不会产生预期的结果。
首先,rand() % N
不能保证产生均匀分布,除非N是可能值数的除数。在任何其他情况下,你会有轻微的偏见。无论如何,我rand
的手册页将其描述为错误的随机数生成器,因此您应该尝试使用random
或arc4random_uniform
。
但是避免索引回到原来的位置既是一致的,也很难实现。我能想象的唯一方法是保留一个数字数组[0; n [和交换它与真实数组相同,以便能够知道数字的原始索引。
代码可能变成:
void Shuffle(int arr[]. size_t n)
{
int i, newIndx;
int *indexes = malloc(n * sizeof(int));
for (i=0; i<n; i++) indexes[i] = i;
for(i=0; i < n - 1; ++i) // beware to the inequality!
{
int i1;
// search if index i is in the [i; n[ current array:
for (i1=i; i1 < n; ++i) {
if (indexes[i1] == i) { // move it to i position
if (i1 != i) { // nothing to do if already at i
swap(i, i1, arr);
swap(i, i1, indexes);
}
break;
}
}
i1 = (i1 == n) ? i : i+1; // we will start the search at i1
// to guarantee that no element keep its place
newIndx = i1 + arc4random_uniform(n - i1);
/* if arc4random is not available:
newIndx = i1 + (random() % (n - i1));
*/
swap(i, newIndx, arr);
swap(i, newIndx, indexes);
}
/* special case: a permutation of [0: n-1[ have left last element in place
* we will exchange the last element with a random one
*/
if (indexes[n-1] == n-1) {
newIndx = arc4random_uniform(n-1)
swap(n-1, newIndx, arr);
swap(n-1, newIndx, indexes);
}
free(indexes); // don't forget to free what we have malloc'ed...
}
注意:算法应该是正确的,但代码尚未经过测试,可能包含错别字......