在看陈硕的Linux多线程服务器编程时 ,看到生成全排列的一种方式,使用stl的next_permutation方法,正好手上有本stl源码剖析,就研究了下这个算法。
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 t = i; --i; if(*i < *t) { BidirectionalIterator j = last; while(!(*i < *--j)); iter_swap(i, j); reverse(t, last); return true; } if(i == first) { reverse(first, last); //全逆向,即为最小字典序列,如cba变为abc return false; } } }
当还能生成下个排列时,返回true,如果不能在生成了,返回false。
这是其实现方式,主要思想就是:从后往前查找相邻的迭代器 i和ii,并使得*i<*ii;再从后往前查找第一个大于i值的迭代器j,将i和j所指内容交换,并将ii到last的内容翻转。
如果i到了begin,且(*i>=*ii),那么说明不能在生成下个排列了,返回false。
利用这个算法生成全排列:
#include <iostream> #include <algorithm> #include <string> using namespace std; int main() { string str; cin >> str; sort(str.begin(), str.end()); cout << str << endl; while (next_permutation(str.begin(), str.end())) { cout << str << endl; } return 0; }
下面自己根据此思想生成的一个方式:
// GetAllPartition.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <VECTOR> #include <iostream> #include <iterator> #include <algorithm> using namespace std; static int num = 0; void getallpartition(vector<int> & v){ vector<int>::iterator i = v.end(); vector<int>::iterator ii; ostream_iterator<int> outite(cout," "); copy(v.begin(),v.end(),outite); cout<<endl; num++; for(;;){ i = v.end(); --i; ii = i; --i; while(!(*i < *ii) ){ --i; --ii; if( i == v.begin() && (*i > *ii)){ return; } } if(*i < *ii){ vector<int>::iterator j = v.end(); while(!(*i < *--j)); iter_swap(i,j); reverse(ii,v.end()); copy(v.begin(),v.end(),outite); cout<<endl; num++; } } } int main(int argc, char* argv[]) { int array[] = {1,2,3,4,5}; vector<int> v(array,array+sizeof(array)/sizeof(int)); getallpartition(v); cout<<num<<endl; return 0; }
附:
iter_swap(iteri,iterj); // 将iteri和iterj所指内容交换
{
T tmp = *iteri;
*iteri = *iterj;
*iterj = tmp;
}
void reverse(BidirectionlIterator first,BidirectionlIterator last);
//双层架构,对BidirectionlIterator和RandomAccessIterator版本 template<class BidirectionlIterator> inline void reverse(BidirectionlIterator first,BidirectionlIterator last){ _reverse(first,last,iterator_category(first)); } template<class BidirectionlIterator> void _reverse(BidirectionlIterator first,BidirectionlIterator last,bidirectional_iterator_tag){ while(true){ if(first == last || first == --last ) return; else iter_swap(first++,last); } } template<class RandomAccessIterator> void _reverse(RandomAccessIterator first,RandomAccessIterator last,random_access_iterator_tag){ while(first < last) //Randomaccessiterator才支持<运算符,从而针对这个版本提高了效率 iter_swap(first++,--last); }