c ++遍历所有邻居排列

时间:2015-06-04 12:14:03

标签: c++ permutation

我有一个N个对象的向量,我想迭代这个向量的所有邻居排列。我称之为邻居排列的是一种排列,其中只有原始向量的两个元素会被改变: 如果我有一个'a','b','c','d'的向量,那么:

'b','a','c','d' //is good
'a','c','b','d' //is good
'b','a','d','c' //is not good (2 permutations)

如果我使用std::next_permutation(myVector.begin(), myVector.end(),那么我将获得所有可能的排列,而不仅仅是"邻居"的...

你知道如何实现这一目标吗?

3 个答案:

答案 0 :(得分:2)

最初,我以为我会过滤hamming distance大于2的排列。

但是,如果你真的只需要通过交换一对来生成所有向量,那么如果你喜欢这样做会更有效:

for(int i = 0; i < n; i++)
    for(int j = i + 1; j < n; j++)
        // swap i and j

根据您是否需要收集所有结果,您应该在交换之前制作副本或向量,或者在处理当前排列后再次交换i和j。

收集所有结果:

std::vector< std::vector<T> > neighbor_permutations;
for(int i = 0; i < n; i++) {
    for(int j = i + 1; j < n; j++) {
        std::vector<T> perm(v);
        std::swap(perm[i], perm[j]);
        neighbor_permutations.push_back(perm);
    }
}

更快的版本 - 不收集结果:

for(int i = 0; i < n; i++) {
    for(int j = i + 1; j < n; j++) {
        std::swap(v[i], v[j]);
        process_permutation(v);
        std::swap(v[i], v[j]);
    }
}

答案 1 :(得分:1)

或许把它分成两部分是个好主意:

  • 如何生成“邻居排列”

  • 如何迭代它们

关于第一个,编写函数很容易:

std::vector<T> make_neighbor_permutation(
    const std::vector<T> &orig, std::size_t i, std::size_t j);

交换 i j 。我不明白你的问题是否有一个额外的约束 j = i + 1 ,在这种情况下你可以删除一个参数。

使用此函数,您现在需要一个迭代器来迭代 i j 的所有合法组合(再次,我不确定您的解释问题。可能有 n - 1 值)。

使用boost::iterator_facade非常容易。您只需要定义一个迭代器,它将构造函数作为原始迭代器,并将 i (可能还有 j )设置为初始值。随着它的增加,它需要更新索引(或索引)。解引用方法需要调用上面的函数。

答案 2 :(得分:0)

获得它的另一种方法,只需一次尝试。

 int main()
    {
        std::vector<char> vec={'b','a','c','d'};
        std::vector<int> vec_in={1,1,0,0};

        do{
             auto it =std::find(vec_in.begin(),vec_in.end(),1);
             if( *(it++) ==1)
             {
                 for(auto &x : vec)
                 {
                     std::cout<<x<<" ";
                 }
                 std::cout<<"\n";
             }

        } while(std::next_permutation(vec_in.begin(),vec_in.end()),  
                std::next_permutation(vec.begin(),vec.end()) );
    }