STL提供了两个用来计算排列组合关系的算法,分别是next_permucation和prev_permutation。解决全排列问题。
首先我们必须了解什么是“下一个”排列组合,什么是“前一个”排列组合。考虑三个字符所组成的序列{a,b, c)。这个序列有六个可能的排列组合: abc,acb,bac,bca,cab,cba。
这些排列组合根据less-than操作符做字典顺序(按照升序排列)的排序。也就是说,abc名列第一,因为每一个元素都小于其后的元素。acb是次一个排列组合,因为它是固定了a(序列内最小元素)之后所做的新组合。同样道理,那些固定b(序列内次小元素)而做的排列组合,在次序上将先于那些固定c而做的排列组合。以bac和 bca为例,bac在 bca之前,因为序列ac小于序列ca。面对bca,我们可以说其前一个排列组合是bac,而其后一个排列组合是cab。序列abc没有“前一个”排列组合,cba没有“后一个”排列组合。
next_permutation ( )会取得〔 first,last)所标示之序列的下一个排列组合。如果没有下一个排列组合,便返回false;否则返回true。
首先,从最尾端开始往前寻找两个相邻元素,令第一元素为*i,第二元素为 *ii,且满足*i< *ii。找到这样一组相邻元素后,再从最尾端开始往前检验,找出第一个大于*i的元素,令为*j,将 i,j元素对调,再将 ii 之后的所有元素颠倒排列。此即所求之“下一个”排列组合。
输入序列{0,1,2,3,4}
第一元素为*i == 3,第二元素为 *ii == 4,且满足*i< *ii. 找到这样一组相邻元素(3 4)
从最尾端开始往前检验,找出第一个大于*i的元素,令为*j == 4
将 i,j元素对调(*i == 4*j == 3),再将 ii 之后的所有元素颠倒排列
输出“下一个”排列组合{0,1,2,4,3};
输入序列{0,1,2,4,3}
第一元素为*i == 2,第二元素为 *ii == 4,且满足*i< *ii. 找到这样一组相邻元素(2 4)
从最尾端开始往前检验,找出第一个大于*i的元素,令为*j == 3
将 i,j元素对调(*i == 3 *j == 2),再将 ii 之后的所有元素颠倒排列 (4 2-->2 4)
输出“下一个”排列组合{0,1,3,2,4};
代码测试求全排列问题:
#includeusing namespace std;bool test_next_permutation(char* first, char* last)
{if(first == last) return false;char* i = first;++i;if(i == last) return false;//只有一个元素i = last; //i指向尾部--i;for(;;){char* ii = i;--i;//以上,以确定一组相邻元素(升序)if(*i < *ii){ //如果前一个小char * j = last; //j指向尾部(尾元素下一个)while(!(*i < *--j));//由尾向前,找到比*i大的元素swap(*i,*j); //交换i,j元素reverse(ii,last);//将ii后全部元素逆序排序return true;}if(i == first){ //进行首元素reverse(first, last);//全部逆向排序return false;}}
}
int main()
{char s[5] = "0123";do{cout<