1.next_permutation 函数原型
template<class BidirectionalIterator>
bool next_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last
);
template<class BidirectionalIterator, class BinaryPredicate>
bool next_permutation(
BidirectionalIterator _First,
BidirectionalIterator _Last,
BinaryPredicate _Comp
);
由函数模板可知,next_permutation返回值为bool型,模板2第三个参数用来表示比较方式,默认形式为小于,当找到下一个全排列序列时返回值为真,若没找到则返回值为假。
(这里解释下何时为找到:对于序列(1,2,3),默认的所有全排列方式为((123),(132),(213),(231),(312),(321)),即当输入为前5个序列时,均能找到下一个排列方式的序列,返回值为真,输入序列为最后(321)时,无下一排列方式序列,返回值为假)
2.next_permutation实现原理
对于一个序列进行全排列,如(123),我们自然会得到((123),(132),(213),(231),(312),(321))所有可能,在书写排列方式的过程中,我们是先将1固定,然后排23,然后2换置第一位,再排13,最后3换置第一位,排12。我们看一个较长的序列(23154),如何找到它下一个序列呢?我们从序列尾部开始依次向前寻找,找到第一个相邻两数(i,ii)满足如下条件i<ii,此处为(1,5);再从尾部开始寻找第一个大于i的数,记为j;交换i,j位置,得到序列(23451),最后,将ii后序列(含ii在内)反转得到序列(23415),此即为(23154)的下一个序列
原理分析:
1.依次向前寻找第一个相邻两个数(i,ii)满足(i<ii):使得ii后数均小于ii,且呈降序排列(***i<ii>*>*>*>...)
2.从尾部开始寻找第一个大于i的数j,交换i,j位置,由于j是(第一个)大于i的数,交换后保证了序列整体的最小递增性(相当于先确定了递增性的最高位)
3.反转ii以及之后序列:使ii及之后序列递增排列,从而确保了低位的最小递增性
4.若序列已经全部降序排列(即i=first),反转序列,返回false
template<class BidirectionalIterator>
bool next_permutation(
BidirectionalIterator first,
BidirectionalIterator last
)
{
if(first == last)
return false; //空序列
BidirectionalIterator i = first;
++i;
if(i == last)
return false; //一个元素,没有下一个序列了
i = last;
--i;
for(;;) {
BidirectionalIterator ii = i;
--i;
if(*i < *ii) {
BidirectionalIterator j = lase;
while(!(*i < *--j));
iter_swap(i, j);
reverse(ii, last);
return true;
}
if(i == first) {
reverse(first, last); //全逆向,即为最小字典序列,如cba变为abc
return false;
}
}
}
#include<iostream>
#include<vector>
#include<iterator>
#include<deque>
#include<algorithm>
using namespace std;
int main()
{
deque<int> d1;
vector<int> v1;
int dim1[]={1,2,3};
v1.assign(dim1,dim1+3);
cout<<"vector v1 : "<<endl;
copy(v1.begin(),v1.end(),ostream_iterator<int>(cout,", " ));
cout<<endl;
cout<<"deque d1(Original) : "<<endl;
copy(v1.begin(),v1.end(),back_inserter(d1));
copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
cout<<endl<<endl;
while(next_permutation(d1.begin(),d1.end()))
{
copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
cout<<endl;
}
cout<<endl;
//全降序排列后反转原序列
copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
cout<<endl;
getchar();
}
4.小结
stl库中next_permutation算法用来输出序列的全排列比较方便,需注意输入序列(数字或字母)为升序时才能得到全部的排列组合,使用时需要包含头文件<algorithm>,当找到最后序列,即全为降序排列时,返回false,序列全部逆转,变为初始的升序排列。,prev_permutation算法的用法类似,只不过是寻找全排列序列中输入序列之前的序列。