在 C++ 中生成字符串的排列

Posted

技术标签:

【中文标题】在 C++ 中生成字符串的排列【英文标题】:Generating permutation of the string in c++ 【发布时间】:2018-07-20 07:49:16 【问题描述】:

这是使用位掩码生成可能排列的代码。当i = 2 , bit = 4 , mask = 7 出现这种情况后,我无法理解它是如何执行的。

bit is 4mask 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 &amp; bit) continue;之前的调试打印弄糊涂了 @UmNyobe 是的,由于递归函数,我无法看到每一步的输出是如何产生的 只是为了帮助调试递归,我建议在函数中添加一个深度参数,以便您可以打印数字或打印缩进空格。 【参考方案1】:

由于您使用的是递归算法,因此您需要在达到终止条件时停止递归(在您的情况下为out.length() == n)。如果触发此条件,您将打印找到的排列,但是在此之后会立即发生什么?您继续执行该功能。特别是,您将遍历将打印一些输出的 for 循环(此时毫无意义,因为您已到达递归的底部)。实际上,您对触发递归终止条件后打印的输出消息感到困惑。将 return 语句添加到您的递归终止检查中:

if (out.length() == n) 
    cout << "OUT: " << out << endl;
    return;

这样您将避免多余的递归调用,并且不会看到可能令人困惑的无关输出消息。

至于您关于为什么掩码不会改变的问题 - 请注意,对于 mask = 7bit = 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++ 中生成随机双精度数

使用 C++ 字符串类函数从较长的原始基因组字符串中生成“基因子字符串”

写入在 Windows 下的 Java 应用程序中生成的 C++ 控制台应用程序

如何使用 Perl 从一组字母中生成单词列表?

在没有映射函数的列表中生成排列

如何在python中生成数组的排列?