试图理解 Knuth 的排列算法
Trying to understand Knuth's algorithm for permutations
我最近在我的一个算法中得到指示 类 使用 Knuth 的算法来创建存储在 malloc 数组中的排列。
设置如下:
array 是指向保存排列的分配数组的指针。它最初存储 n 个值,每个位置保存索引 + 1。
因此,如果 n 为 10,则数组最初为:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
"rand" 变量保存从 1 到 n 的一些变量。 (在这个例子中,1-10)。
Swap 应该是一个执行位异或交换 (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)
然后我们尝试对两个参数进行异或运算:
首先:&array[i]
这是指向分配数组的指针的地址。 (双指针,对吧?)
和第二个参数完全一样。指向分配数组的指针的地址。
我到底应该如何以及为什么要对地址进行异或运算?
我有什么不明白的?
感谢所有帮助!
首先,交换不应该做按位异或。它应该交换。
通常是这样写的:
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;
}
这可能是某人在交换中执行 XOR 的意思。
其次,rand 的范围必须从 0 到 i,而不是 1 到 n,如果您想要一个无偏随机排列。
给定 rand(x) returns [0,x] 中的一个数字,你想要这样的东西:
for (int i=n-1; i>0; --i)
{
j = rand(i);
if (i!=j)
{
swap(&array[i],&array[j]);
}
}
它的工作方式很简单:对于每个数组[i],它从尚未选取的元素中随机选择一个元素。
我最近在我的一个算法中得到指示 类 使用 Knuth 的算法来创建存储在 malloc 数组中的排列。
设置如下:
array 是指向保存排列的分配数组的指针。它最初存储 n 个值,每个位置保存索引 + 1。
因此,如果 n 为 10,则数组最初为:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
"rand" 变量保存从 1 到 n 的一些变量。 (在这个例子中,1-10)。
Swap 应该是一个执行位异或交换 (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)
然后我们尝试对两个参数进行异或运算:
首先:&array[i]
这是指向分配数组的指针的地址。 (双指针,对吧?)
和第二个参数完全一样。指向分配数组的指针的地址。
我到底应该如何以及为什么要对地址进行异或运算?
我有什么不明白的?
感谢所有帮助!
首先,交换不应该做按位异或。它应该交换。
通常是这样写的:
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;
}
这可能是某人在交换中执行 XOR 的意思。
其次,rand 的范围必须从 0 到 i,而不是 1 到 n,如果您想要一个无偏随机排列。
给定 rand(x) returns [0,x] 中的一个数字,你想要这样的东西:
for (int i=n-1; i>0; --i)
{
j = rand(i);
if (i!=j)
{
swap(&array[i],&array[j]);
}
}
它的工作方式很简单:对于每个数组[i],它从尚未选取的元素中随机选择一个元素。