Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有人能给我解释一下这个生成给定集合所有可能置换的代码吗?_C++_Algorithm_Recursion_Set_Permutation - Fatal编程技术网

C++ 有人能给我解释一下这个生成给定集合所有可能置换的代码吗?

C++ 有人能给我解释一下这个生成给定集合所有可能置换的代码吗?,c++,algorithm,recursion,set,permutation,C++,Algorithm,Recursion,Set,Permutation,我在 竞争对手的《程序员手册》也这么做了,但我很难理解它背后的逻辑。 它指出: 与子集一样,可以使用递归生成置换。以下 函数搜索遍历集合{0,1,…,n{1}的排列。这个 函数构建包含置换的向量置换,并 在调用不带参数的函数时开始搜索。 每个函数调用都会向排列添加一个新元素。选择的阵列 指示排列中已包含哪些元素。如果 置换等于集合的大小,已生成置换。 我似乎无法理解正确的直觉和使用的概念。 有人能给我解释一下代码在做什么以及背后的逻辑吗?你可以这样分解代码: void search() {

我在 竞争对手的《程序员手册》也这么做了,但我很难理解它背后的逻辑。 它指出:

与子集一样,可以使用递归生成置换。以下 函数搜索遍历集合{0,1,…,n{1}的排列。这个 函数构建包含置换的向量置换,并 在调用不带参数的函数时开始搜索。

每个函数调用都会向排列添加一个新元素。选择的阵列 指示排列中已包含哪些元素。如果 置换等于集合的大小,已生成置换。

我似乎无法理解正确的直觉和使用的概念。
有人能给我解释一下代码在做什么以及背后的逻辑吗?

你可以这样分解代码:

void search() {
    if (permutation.size() == n) {
        // we have a valid permutation here
        // process permutation
    } else {

        // The permutation is 'under construction'.
        // The first k elements are fixed,
        // n - k are still missing.
        // So we must choose the next number:
        for (int i = 0; i < n; i++) {

            // some of them are already chosen earlier
            if (chosen[i]) continue;

            // if i is still free:

            // signal to nested calls that i is occupied
            chosen[i] = true;
            // add it to the permutation
            permutation.push_back(i);

            // At the start of this nested call,
            // the permutation will have the first (k + 1)
            // numbers fixed.
            search();

            // Now we UNDO what we did before the recursive call
            // and the permutation state becomes the same as when
            // we entered this call.
            // This allows us to proceed to the next iteration
            // of the for loop.

            chosen[i] = false;
            permutation.pop_back();
        }
    }
}
直觉可能是,搜索以各种可能的方式完成当前部分构造的排列,并处理所有排列

如果已经完成,我们只需要处理一个可能的排列。
如果没有,我们可以首先以各种可能的方式选择第一个数字,然后,对于其中的每一个,递归地完成排列。

您可以像这样拆分代码:

void search() {
    if (permutation.size() == n) {
        // we have a valid permutation here
        // process permutation
    } else {

        // The permutation is 'under construction'.
        // The first k elements are fixed,
        // n - k are still missing.
        // So we must choose the next number:
        for (int i = 0; i < n; i++) {

            // some of them are already chosen earlier
            if (chosen[i]) continue;

            // if i is still free:

            // signal to nested calls that i is occupied
            chosen[i] = true;
            // add it to the permutation
            permutation.push_back(i);

            // At the start of this nested call,
            // the permutation will have the first (k + 1)
            // numbers fixed.
            search();

            // Now we UNDO what we did before the recursive call
            // and the permutation state becomes the same as when
            // we entered this call.
            // This allows us to proceed to the next iteration
            // of the for loop.

            chosen[i] = false;
            permutation.pop_back();
        }
    }
}
直觉可能是,搜索以各种可能的方式完成当前部分构造的排列,并处理所有排列

如果已经完成,我们只需要处理一个可能的排列。
如果没有,我们可以先用各种可能的方法选择第一个数字,然后,对于其中的每一个,递归地完成排列。

我将尝试给你一些直觉。主要的想法是回溯。您基本上构建了一个解决方案,直到面临死胡同。当你面对一条死胡同时,回到最后一个位置,在那里你可以做一些与上次不同的事情。让我浏览一下我为n=3绘制的模拟

首先,你什么都没有。先拿1,然后拿2,再拿3。你现在无处可去,即死胡同。你打印你当前的排列是123你现在做什么?返回到1,因为您知道,通过这次选择3,您可以创建另一条路径。那么这次你用同样的方法得到了什么?132 . 你能用1做更多的事情吗?不。现在回到什么都没有的状态,重新开始同样的事情,现在是2。你现在明白了,对吧

对于代码中发生的相同事情:

无效搜索{ 如果permutation.size==n///死胡同 { //过程置换 } 否则{ 对于int i=0;i我会给你一些直觉。主要的想法是回溯。您基本上构建了一个解决方案,直到面临死胡同。当你面对一条死胡同时,回到最后一个位置,在那里你可以做一些与上次不同的事情。让我浏览一下我为n=3绘制的模拟

首先,你什么都没有。先拿1,然后拿2,再拿3。你现在无处可去,即死胡同。你打印你当前的排列是123你现在做什么?返回到1,因为您知道,通过这次选择3,您可以创建另一条路径。那么这次你用同样的方法得到了什么?132 . 你能用1做更多的事情吗?不。现在回到什么都没有的状态,重新开始同样的事情,现在是2。你现在明白了,对吧

对于代码中发生的相同事情:

无效搜索{ 如果permutation.size==n///死胡同 { //过程置换 } 否则{ 对于int i=0;i使用n==3用铅笔和纸运行它。将每个元素逐个添加到当前排列中,然后递归生成具有此前缀的剩余元素的所有排列,之后,再次删除此级别的当前元素并继续下一个元素,直到没有更多的元素可供尝试。有一个更好的解决方案是使用:。使用n==3使用铅笔和纸运行它。添加每个e
逐个删除当前排列,然后递归生成具有此前缀的剩余元素的所有排列,然后再次删除此级别的当前元素并继续下一个,直到没有更多的元素可供尝试。使用有更好的解决方案:。