排列生成算法
2015-03-03 16:33
267 查看
以集合1~n为研究对象,将自己所遇到的几种排列生成算法总结一下。
方法一:
算法:
1.从右向左找到第一个值减小的的元素,假设为s[i];
2.从右向左找到第一个比s[i]大的元素,假设为s[k];
3.交换s[i]与s[k]的值;
4.对s[i]后面的子串逆序;
代码:
方法二:
利用递归的方法实现全排列。类似于DFS,遍历每一位可以取到的满足条件的值,使用之后进行标记。
代码:
方法三:
使用STL中自带的next_permutation()函数。next_permutation()函数是按照字典序来生成下一个排列的,及时有重复的元素也会生成所有的排列;
代码:
标注:同理,如果想生成任意集合的排列,可以将上述方法中生成的排列对应为目标集合的下标。
方法一:
算法:
1.从右向左找到第一个值减小的的元素,假设为s[i];
2.从右向左找到第一个比s[i]大的元素,假设为s[k];
3.交换s[i]与s[k]的值;
4.对s[i]后面的子串逆序;
代码:
void next_perm(int s[],int n) { int i,k,p,q; i=n-1; while( s[i] > s[i+1] ) i--; k=n; while( s[i] > s[k] ) k--; swap(s[i],s[k]); p=i+1;q=n; while( p < q ) { swap(s[p],s[q]); p++; q--; } return ; }
方法二:
利用递归的方法实现全排列。类似于DFS,遍历每一位可以取到的满足条件的值,使用之后进行标记。
代码:
bool used[MAX_N]; int perm[MAX_N]; void permutation(int pos,int n) { if( pos == n ) { /* *对新生成队列的操作 */ return ; } //针对perm的第pos个位置,究竟是用1~n中的哪一个进行循环 for( int i = 1; i <= n; i++ ) { if( !used[i] ) { used[i]=true; permutation( pos+1,n ); used[i]=false; } } return ; }
方法三:
使用STL中自带的next_permutation()函数。next_permutation()函数是按照字典序来生成下一个排列的,及时有重复的元素也会生成所有的排列;
代码:
int perm[MAX_N]; void permutatiom( int n ) { for( int i = 0; i < n; i++ ) perm[i]=i+1; do{ /* *对排列的操作 */ }while( next_permutation( perm, perm+n ) ) //所有排列生成后,返回false return ; }
标注:同理,如果想生成任意集合的排列,可以将上述方法中生成的排列对应为目标集合的下标。