在C ++中生成复合排列的绝佳方法

时间:2018-10-21 21:03:49

标签: c++ stl permutation

我有一个Test类,其中包含两个Letter类的向量,这是一个用户定义的类型,已实现了小于运算符(<)。如何最好地生成Test的所有可能排列?

class Test
{
  vector<Letter> letter_box_a;
  vector<Letter> letter_box_b;
}

因此,如果letter_box_a包含字母A和B,而letter_box_b包含字母C和D,则Test的有效排列为(AB)(CD),(BA)(CD),(AB)(DC)和(BA)( DC)。

尽管我能够蛮力,但是我试图编写一个更好的(更优雅/更有效)的函数,该函数在底层容器上内部调用std :: next_permutation

Test test;
while (test.set_next_permutation())
{
    // Do the stuff
}

,但似乎比我最初预期的要复杂一些。我不一定需要STL解决方案,但想要一个优雅的解决方案。

2 个答案:

答案 0 :(得分:0)

如果要使用std::next_permutation,则需要对要排列的每个向量进行嵌套循环:

std::string s0 = "ab";
std::string s1 = "cd";

do
{
    do
    {
        cout << s0 << "" << s1 << endl;
    } while (std::next_permutation(s0.begin(), s0.end()));
} while (std::next_permutation(s1.begin(), s1.end()));

输出:

abcd
bacd
abdc
badc

而且,在班上:

class Foo
{
public:
    Foo(std::string_view arg_a, std::string_view arg_b)
        : a(arg_a)
        , b(arg_b)
        , last(false)
    { }

    void reset_permutations()
    {
        last = false;
    }

    bool next_permutation(std::string& r)
    {
        if (last)
            return false;

        if (not std::next_permutation(a.begin(), a.end()))
            if (not std::next_permutation(b.begin(), b.end()))
                last = true;

        r = a + b;
        return true;
    }

private:
    std::string a, b;
    bool last;
};

int main(int argc, const char *argv[])
{
    Foo foo("ab", "cd");
    string s;
    while (foo.next_permutation(s))
        cout << s << endl;
    return 0;
}

答案 1 :(得分:0)

我认为您可以做类似的事情

bool Test::set_next_permutation() {
    auto &a = letter_box_a, &b = letter_box_b;  // entirely to shorten the next line
    return std::next_permutation(a.start(), a.end()) || std::next_permutation(b.start(), b.end());
}

(当然,while循环在任何情况下都会跳过初始排列。您希望使用do ... while循环。)