在 C++ 中生成字符串的排列
Posted
技术标签:
【中文标题】在 C++ 中生成字符串的排列【英文标题】:Generating permutation of the string in c++ 【发布时间】:2018-07-20 07:49:16 【问题描述】:这是使用位掩码生成可能排列的代码。当i = 2 , bit = 4 , mask = 7
出现这种情况后,我无法理解它是如何执行的。
当bit is 4
和mask is 7
如此条件(bit & mask) == true
所以它会继续。如何再次i = 2?以及当Mask在执行recurse(....)时会改变时,mask如何变为1
#include <iostream>
#include <string>
using namespace std;
void recurse(string s, int mask = 0,string out = "")
int n = s.length();
if (out.length() == n) cout << ' ' << out<<endl;
for (int i = 0; i < n; i++)
cout<<"I:"<<i<<"=>";
unsigned bit = 1 << i;
cout<<bit<< " -> " <<mask<<endl;
cout<<"cond:"<<(mask & bit)<<endl;
if (mask & bit) continue;
cout<<out+s[i]<<endl;
recurse(s, mask | bit, out + s[i]);
int main()
string test = "red";
recurse(test);
cout << endl;
return 0;
输出:
I:0=>1 -> 0
cond:0
r
I:0=>1 -> 1
cond:1
I:1=>2 -> 1
cond:0
re
I:0=>1 -> 3
cond:1
I:1=>2 -> 3
cond:2
I:2=>4 -> 3
cond:0
red
red
I:0=>1 -> 7
cond:1
I:1=>2 -> 7
cond:2
I:2=>4 -> 7 <===== here when bit is 4 and mask is 7 so condition (bit & mask) == true
cond:4 So it will continue .How i = 2 again ? and how mask becomes 1 when Mask will change when it will execute recurse(....)
I:2=>4 -> 1
cond:0
rd
I:0=>1 -> 5
【问题讨论】:
你知道std::next_permutation吗?尤其是示例部分,您可能会很感兴趣。 @lubgr 是的,我知道,但我想通过位掩码方法来实现。 你被if (mask & bit) continue;
之前的调试打印弄糊涂了
@UmNyobe 是的,由于递归函数,我无法看到每一步的输出是如何产生的
只是为了帮助调试递归,我建议在函数中添加一个深度参数,以便您可以打印数字或打印缩进空格。
【参考方案1】:
由于您使用的是递归算法,因此您需要在达到终止条件时停止递归(在您的情况下为out.length() == n
)。如果触发此条件,您将打印找到的排列,但是在此之后会立即发生什么?您继续执行该功能。特别是,您将遍历将打印一些输出的 for 循环(此时毫无意义,因为您已到达递归的底部)。实际上,您对触发递归终止条件后打印的输出消息感到困惑。将 return 语句添加到您的递归终止检查中:
if (out.length() == n)
cout << "OUT: " << out << endl;
return;
这样您将避免多余的递归调用,并且不会看到可能令人困惑的无关输出消息。
至于您关于为什么掩码不会改变的问题 - 请注意,对于 mask = 7
和 bit = 4
的值,您会得到 maks | bit = 7| 4 = 7 = mask
。所以在某些情况下,按位 OR-ing 掩码和位不会影响掩码。
【讨论】:
Since you are using recursive algorithm, you need to stop recursing somewhere.
从技术上讲它确实停止了。【参考方案2】:
在 continue i = 3 之后,由于 n = 3 循环停止。 所以它上升了一个递归步骤并从循环继续:
I:0=>1 -> 1
cond:1
I:1=>2 -> 1
cond:0
re
您可以尝试打印一个类似“已完成循环”的语句来查看此内容。
我希望这能回答你的问题。
【讨论】:
它是否与堆栈概念有关。实际上,如果发生递归,我会从上到下移动,然后我会向上做同样的事情。我猜你不能像这样想象它,因为它在那种情况下失败了。 与栈概念有关。你的问题的时间是在递归深度 3,然后它完成了两个完整的方法,因此在递归深度 1 并再次进入 i==2 的语句以上是关于在 C++ 中生成字符串的排列的主要内容,如果未能解决你的问题,请参考以下文章
使用 C++ 字符串类函数从较长的原始基因组字符串中生成“基因子字符串”