我有一个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()
,那么我将获得所有可能的排列,而不仅仅是"邻居"的...
你知道如何实现这一目标吗?
答案 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()) );
}