随机置换生成

时间:2014-04-04 23:03:51

标签: c function random permutation

我很难从我的教科书中理解这段代码示例。我希望有人可以更好地解释这部分代码然后我的书。对于这个程序中缺乏评论我很抱歉,所以我会尽力在我要求的内容中非常具体。好的标题表明该程序是“随机排列生成”。我在代码中感到困惑的地方是名为bldPerm()

的函数

功能bldPerm():

    void bldPerm(int randNos[])
{
    int oneRandno;
    int haveRand[ARY_SIZE] = { 0 };

    for (int i = 0 ; i < ARY_SIZE; i++)
    {
        do
        {
            oneRandno = rand() % ARY_SIZE;
        } while (haveRand[oneRandno] == 1);
        haveRand[oneRandno] = 1;
        randNos[i] = oneRandno;
    }
    return;
}

我不明白while while循环while(haveRand[oneRandno]) == 1;如何以及为什么通过将它与1进行比较来检查数组。然后让我感到困惑的是haveRand[oneRandno] = 1;在该元素中设置为1。然后该元素为“1”被设置为randNos[i] = oneRandno;并返回除1之外的其他数字。该程序在我的书中工作并打印出其他数字然后1但我只是看不出它是如何工作的。我一直试图扭曲我的头脑,我确信这是一件简单的事情......但我不明白。所以我的问题是,任何人都可以详细解释这个函数中发生了什么以及它是如何工作的吗?

完整代码:

#define _CRT_SECURE_NO_WARNINGS
#define ARY_SIZE 20
#include <stdio.h>
#include <stdlib.h>

void bldPerm(int randNos[]);
void printData(int data[], int size, int linesSize);

int main(void)
{
    int randNos[ARY_SIZE];

    printf("Begin Random Permutation Generation\n");
    bldPerm(randNos);
    printData(randNos, ARY_SIZE, 10);

    return 0;
}


void bldPerm(int randNos[])
{
    int oneRandno;
    int haveRand[ARY_SIZE] = { 0 };

    for (int i = 0 ; i < ARY_SIZE; i++)
    {
        do
        {
            oneRandno = rand() % ARY_SIZE;
        } while (haveRand[oneRandno] == 1);
        haveRand[oneRandno] = 1;
        randNos[i] = oneRandno;
    }
    return;
}
void printData(int data[], int size, int linesSize)
{
    int numPrinted = 0;

    printf("\n");
    for (int i = 0; i < size; i++)
    {
        numPrinted++;
        printf("%2d ", data[i]);
        if (numPrinted >= linesSize)
        {
            printf("\n");
            numPrinted = 0;
        }
    }
    printf("\n");
    return;
}

2 个答案:

答案 0 :(得分:2)

我们希望用数字0,...,ARY_SIZE-1的随机排列填充数组。这意味着这些数字是完全随机排列的。

void bldPerm(int randNos[]) {
    int oneRandno;

我们保留一个名为haveRand的数组,指示是否已为我们的排列选择了数字i。如果选择了号码,haveRand[i]将设置为1.开头没有选择号码,因此我们使用0对其进行初始化。

    int haveRand[ARY_SIZE] = { 0 };

对于输出数组中的每个位置,我们随机选择一个尚未选择的数字。

    for (int i = 0 ; i < ARY_SIZE; i++)
    {

让我们找一个尚未被选中的号码。

        do
        {

为此,我们对任意随机数进行采样并将其称为oneRandno

            oneRandno = rand() % ARY_SIZE;

我们检查是否尚未选择。如果是这种情况,那么haveRand[oneRandno]为0,而while看起来就完成了。否则我们继续尝试新的。

        } while (haveRand[oneRandno] == 1);

不是我们通过将haveRand[oneRandno]设置为1来标记所选的数字。

        haveRand[oneRandno] = 1;

将所选数字写入输出数组。

        randNos[i] = oneRandno;
    }
}

这个算法实际上非常糟糕......例如,为了填充最后一个元素,只剩下一个候选者,因为已经选择了所有其他数字。但是while循环试图通过随机抽样找到这个数字,这可能需要很长时间。

我建议创建一个数字为0到ARY_SIZE-1的数组,并使用Fisher-Yates algorithm对它们进行随机播放。

答案 1 :(得分:1)

我浏览了代码并用代码写了一些评论,希望能够清除它。

void bldPerm(int randNos[]) // here you give an array of random numbers that is empty
{
    // declare an int to store the randomly generated number
    int oneRandno;

    // initialize an array to store random numbers of size ARY_SIZE
    int haveRand[ARY_SIZE] = { 0 };

    // now loop while i is smaller then ARY_SIZE and increment i
    for (int i = 0 ; i < ARY_SIZE; i++)
    {
        // here do generate the random number
        do
        {
            // oneRandno will ALWAYS be between -1 and ARY_SIZE
            // or i.o.w. from 0 to ARY_SIZE - 1
            oneRandno = rand() % ARY_SIZE;
        } 
        // because the numbers have to be unique, if oneRandno
        // was already generated loop again
        while (haveRand[oneRandno] == 1);

        // Set to 1 because the next iteration oneRandno could have the same value,
        // however very unlikely because rand() has a period of at least 2^32 which 
        // gives you enough room to have it generate a whole lot of numbers before 
        // it generates the same number again. So basically the while loop will 
        // never loop and act like a glorified if statement.
        // and that the values in randNos should unique, if oneRandno has the 
        // same value the do while loop will iterate once more 
        // and generate another oneRandno
        haveRand[oneRandno] = 1;

        // finally store the uniquely generated number
        randNos[i] = oneRandno;

        //go to the next iteration
    }
    return;
}