我正在尝试一个示例程序来掌握prev和next排列之间的区别。但是,我的程序似乎没有正常工作。我通过询问数组中的元素数量来启动程序,并使用简单的for循环
构建数组for(i = 0; i < x; i++)
ptr[i] = i;
cout << "Possible permuations using prev_permutation: " << endl;
do{
for(i = 0; i < x; i++)
cout << ptr[i] << " ";
cout << endl;
} while(prev_permutation(ptr, ptr+x));
cout << "Possible permuations using next_permutation: " << endl;
do{
for(i = 0; i < x; i++)
cout << ptr[i] << " ";
cout << endl;
} while(next_permutation(ptr, ptr+x));
当我使用3个元素的样本运行代码时,(0,1,2)。 prev_permutation给了我(0,1,2,那就是它)。然后next_permutation给了我(2,1,0)。但是,当我评论prev_permutation部分的代码时,当只有next_permutation运行时,我得到一个适当的6个不同的集合排列(0,1,2)。我似乎无法理解发生了什么。
答案 0 :(得分:8)
prev_permutation
和next_permutation
以字典(“按字母顺序”)顺序生成所有排列,并且一旦周期完成后返回false
(即,在调用prev_permutation
之后第一个排列或在最后一个调用next_permutation
之后。)
当您使用字典顺序的第一个排列准备数组时,会调用prev_permutation
。这是第一个,因此prev_permutation
将数组设置为最后一个排列并返回false
,因此您退出循环。
现在您输入next_permutation
循环,但数组的当前内容是按字典顺序排列的最后一个排列,因此next_permutation
将设置第一个排列并返回false。
如果您移除prev_permutation
部分,next_permutation
的循环将从第一个开始,因此它会在返回false
之前正确生成所有6个排列。
您可以考虑按顺序列出的所有排列以及当前配置作为此列表中的指针来可视化效果:
0-1-2 << you start here
0-2-1
1-0-2
1-2-0
2-0-1
2-1-0
在致电next_permutation
时,您正在向下移动,在致电prev_permutation
时,您正在向上移动。当我们走到列表之外时,两个函数都会将指针移动到另一端并返回false
以通知您这一事实。
如果您从prev
开始,则转到2-1-0
并且函数返回false
,然后调用next
,函数将移至0-1-2
并返回{ {1}}再次。
例如,使用false
,0
和1
代替两个零和三个的排列,词典排序为:
2
所以要枚举所有这些内容,您需要从0-0-1-1-1
0-1-0-1-1
0-1-1-0-1
0-1-1-1-0
1-0-0-1-1
1-0-1-0-1
1-0-1-1-0
1-1-0-0-1
1-1-0-1-0
1-1-1-0-0
开始并使用0-0-1-1-1
,或者您需要从next_permutation
开始并使用1-1-1-0-0
。
在这种情况下,在最后一个prev_permutation
上调用next_permutation
将更改为第一个1-1-1-0-0
,并将返回0-0-1-1-1
;以类似的方式调用false
上的prev_permutation
会更改为0-0-1-1-1
,并会因为翻转而返回1-1-1-0-0
。
答案 1 :(得分:3)
prev_permutation
和next_permutation
考虑的所有排列都有明确定义的词典顺序。您提供给他们的数组按此顺序有一些位置。
这就是为什么这两种功能都不能保证提供所有排列的原因。
如果您向prev_permutation
提供了第一个可能的排列,那么您之前就不会有排列。同样,如果您的数组定义为(2,1,0),next_permutation
将不会提供任何新的排列。
如果您需要某些收藏品的所有排列,则需要先sort
收藏,然后使用next_permutation
。