C ++一组字符串的所有排列

时间:2019-06-26 08:13:44

标签: c++ combinations

我正在尝试在向量中生成字符串的所有排列。例如,对于

vector<string> vs = { "a", "b", "c"}; 

我编写了以下代码:

do{
    for (string s : vs)
        cout << s << " ";
    cout << endl;
} while (std::next_permutation(vs.begin(), vs.end()));

我的输出是:

  

a b c
  a c b
  b a c
  b c a
  c a b
  c b a

但是,我缺少

之类的组合
  

a
  a b
  b a
  c

等等。

我想修改我的代码,使其也包括这些安排。怎么做?谢谢!

2 个答案:

答案 0 :(得分:2)

您可以通过以下方式实施功率设置:

bool increase(std::vector<bool>& bs)
{
    for (std::size_t i = 0; i != bs.size(); ++i) {
        bs[i] = !bs[i];
        if (bs[i] == true) {
            return true;
        }
    }
    return false; // overflow
}

template <typename T>
void PowerSet(const std::vector<T>& v)
{
    std::vector<bool> bitset(v.size());

    do {
        for (std::size_t i = 0; i != v.size(); ++i) {
            if (bitset[i]) {
                std::cout << v[i] << " ";
            }
        }
        std::cout << std::endl;
    } while (increase(bitset));
}

Demo

然后对每个集合进行排列,例如:

bool increase(std::vector<bool>& bs)
{
    for (std::size_t i = 0; i != bs.size(); ++i) {
        bs[i] = !bs[i];
        if (bs[i] == true) {
            return true;
        }
    }
    return false; // overflow
}

template <typename T, typename F>
void PowerSet(const std::vector<T>& v, F f)
{
    std::vector<bool> bitset(v.size());

    do {
        f(v, bitset);
    } while (increase(bitset));
}

template <typename T, typename F>
void AllArrangements(const std::vector<T>& v, F f)
{
    PowerSet(v, [f](const std::vector<T>& v, const std::vector<bool>& bitset){
        std::vector<T> toPermute;
        for (std::size_t i = 0; i != v.size(); ++i) {
            if (bitset[i]) {
                toPermute.push_back(v[i]);
            }
        }
        do {
            f(toPermute);
        } while (std::next_permutation(toPermute.begin(), toPermute.end()));
    });
}

Demo

答案 1 :(得分:2)

您的示例表明,您不仅要输出输入的每个子集(Power set),而且还要输出每个集合的所有排列。

我不知道用于此目的的特定术语,但是OEIS A000522称这些“安排”。

要获得所需的内容,您必须将代码与Jarod的部分答案(或您可以在此处找到的任何其他电源设置实现)结合起来:

void outputAllPermutations(std::vector<std::string> input)
{
    // assert(std::is_sorted(input.begin(), input.end()));
    do
    {
        for (std::string s : input)
            std::cout << s << " ";
        std::cout << std::endl;
    } while (std::next_permutation(input.begin(), input.end()));
}

bool isBitSet(unsigned bitset, std::size_t i)
{
    return (bitset & (1 << i)) != 0;
}

void outputAllArrangements(const std::vector<std::string>& input)
{
    // assert(std::is_sorted(input.begin(), input.end()));
    // assert(input.size() < std::sizeof(unsigned) * 8);

    unsigned bitset = 0;

    std::vector<std::string> subset{};
    subset.reserve(input.size());

    for (unsigned bitset = 0; bitset < (1 << input.size()); ++bitset)
    {
        subset.clear();
        for (std::size_t i = 0; i != input.size(); ++i)
            if (isBitSet(bitset, i))
                subset.push_back(input[i]);

        outputAllPermutations(subset);
    }
}

Demo including example output

我使用unsigned代替了std::vector<bool>,因为我发现总体增量逻辑更容易以这种方式进行推理。从理论上讲,这会将代码“限制”为小于32个字符串(或64个字符串,具体取决于平台)的输入,但是看到输入长度22已经花thousands of years来以每个输出1个CPU周期的速度输出,我对此感到满意。