如何创建数组的随机排列?

时间:2013-04-12 00:27:17

标签: c

我在C中编写了这个函数,我想让它创建一个随机排列或从1到n的数字列表。我无法让它没有重复的数字。所以,如果你有n = 4,我希望它只返回一个包含1-4的随机数组,例如:{1,3,4,2}

int* random(int n) 
{
    int* r = malloc(n * sizeof(int));
    // initial range of numbers
    for(int i=0;i<n;++i){
        r[i]=i+1;
    }
    // shuffle
    for (int i = 1; i <= n; ++i){
        int j = rand() % i;
        r[i] = r[j];
        r[j] = i;
  }
  return r;
}

3 个答案:

答案 0 :(得分:10)

将您的第二个for循环更改为:

for (int i = n-1; i >= 0; --i){
    //generate a random number [0, n-1]
    int j = rand() % (i+1);

    //swap the last element with element at random index
    int temp = r[i];
    r[i] = r[j];
    r[j] = temp;
}

这是Fisher-Yates改组算法。我听说使用rand() % n没有统一分发,你已经被警告了。

如果您希望每次都生成唯一的排列,您可以将生成的排列存储在DictionaryHashmap中,然后在每次返回时进行查找。我不认为C内置了一个,但应该有可用的库。

答案 1 :(得分:0)

它可能不是最有效的方法,但由于你已经在开始时填充数组,你可以只循环遍历元素,并为每个元素选择1到n范围内的随机索引,并与该项交换:

int* random(int n) 
{
    int* r = malloc(n * sizeof(int));
    for(int i=0;i<n;++i){
        r[i]=i+1;
    }
    for(int i=0; i<n; ++i){
        int randIdx = rand() % n;
        // swap r[i] with r[randIdx]
        int t = r[i];
        r[i] = r[randIdx];
        r[randIdx] = t;
    }
  return r;
}

我不知道这是否是最有效的,或者即使它给出了最好的分布。但这很简单: - )

答案 2 :(得分:0)

如果你想多次重复以上,又不想每次都得到相同的排列,只需在开头添加以下行:

srand((unsigned)time(NULL));