c语言 - 试图理解高德纳的排列算法



我最近在我的一个算法类中被指示使用Knuth的算法来创建存储在malloc'd数组中的排列。

这是设置:

数组

是指向保存排列的错位数组的指针。它最初存储 n 个值,每个位置持有索引 + 1。

因此,如果 n 为 10,则数组最初为:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

"rand"变量包含从1到n的某个变量(在本例中为1-10)。

交换应该

是一个执行位独占或交换(XOR)的函数。

最终结果应该是 1-n 的某种排列。

因此,[5, 6, 2, 8, 7, 4, 1, 3, 10, 9] 作为一种可能的排列是有效的。

但是,[1, 1, 5, 7, 8, 2, 3, 5, 5, 6] 将无效,因为它不是排列。它有重复项。

但是我无法确定我们被告知使用的这段代码的正面或反面:

for(i = 1; i < n; i++) {
    swap(&array[i], &a[rand]);
}

所以我们从数组的第二个元素开始。(i = 1)

然后,我们尝试对两个参数进行 XOR 运算:

第一个:&数组[i]

这是指向错误定位数组的指针的地址。(双指针,对吧?

第二个参数是完全相同的。指向错误定位数组的指针的地址。

我到底应该如何以及为什么应该对地址进行异或?

我不明白什么?

感谢您的任何帮助!

首先,swap 不应该做按位独占 or。 它应该交换。

通常,这是写的:

void swap(int *a, int *b)
{
    int t=*a;
    *a=*b;
    *b=t;
}

但是有一个使用 XOR 的技巧不需要额外的变量。 您可以像这样实现交换:

void swap(int *a, int *b)
{
    *a^=*b;
    *b^=*a;
    *a^=*b;
}

这可能就是某人在交换中进行异或的意思。

其次,兰德的范围必须从0到i,而不是1到n,你想要一个无偏的随机排列。

给定 rand(x) 返回 [0,x] 中的数字,您需要这样的东西:

for (int i=n-1; i>0; --i)
{
    j = rand(i);
    if (i!=j)
    {
        swap(&array[i],&array[j]);
    }
}

它的工作方式很简单:对于每个数组[i],它从尚未选择的元素中随机选择一个元素。

相关内容

  • 没有找到相关文章

最新更新