一、递归全排列(这段排列是可去重的全排列)
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int sum=0;
bool isSwap(char *list, int begin, int end) {//避免重复
for (int i = begin; i < end; i++){
if (list[i] == list[end])
return false;
}
return true;
}
void SWAP(char *A,int x,int y)//用于交换数组的两个数
{
int temp=A[x];
A[x]=A[y];
A[y]=temp;
}
void perm(char A[], int i, int n){
int j;
if (i == n) {
cout<<A<<endl;
sum++;
}
else {
for (j = i; j <n; j++){
if (isSwap(A, i, j)) {
//使用宏定义,传的是数值,如果这的swap用函数实现,传的应该是指针
SWAP(A,i,j);
//交互位置后,输出以list[j]不变,后面的字母改变的所有排列
perm(A, i + 1, n);
SWAP(A,i,j);
}
}
}
}
int main()
{
char s[105];
while(scanf("%s",s)!=EOF)
{
sum=0;
int len=strlen(s);//数组长度
perm(s,0,len);
cout<<sum;
}
}
二、STL实现
有时候递归的效率使得我们不得不考虑除此之外的其它实现,非常多把递归算法转换到非递归形式的算法是比较难的,这个时候我们不要忘记了标准模板库已经实现的那些算法,这让我们非常轻松。STL有一个函数next_permutation(),它的作用是假设对于一个序列,存在依照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。注意,为了产生全排列,这个序列要是有序的,也就是说要调用一次sort。实现非常easy,我们看一下代码:
(1)char数组排列
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
void permutation(char* str,int length)
{
sort(str,str+length);
do
{
for(int i=0;i<length;i++)
cout<<str[i];
cout<<endl;
}while(next_permutation(str,str+length));
}
int main(void)
{
const int n=105;
char str[n];
cin>>str;
cout<<str<<"全部全排列的结果为:"<<endl;
permutation(str,strlen(str));
return 0;
}
(2)string类排列
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
void permutation(string str,int length)
{
sort(str.begin(),str.end());//注意这里和char类型的不同
do
{
for(int i=0;i<length;i++)
cout<<str[i];
cout<<endl;
}while(next_permutation(str.begin(),str.end()));//注意
}
int main(void)
{
string str;
cin>>str;
cout<<str<<"全部全排列的结果为:"<<endl;
permutation(str,str.size());
return 0;
}
三、有一定约束条件的全排列
对数1,2,3,4,5要实现全排序。要求4必须在3的左边,其他的数位置任意。
思路:首先使用上面的2种方法之中的一个实现全排列,然后对全排列进行筛选,筛选出4在3左边的排列。
#include <iostream>
#include <algorithm>
using namespace std;
void permutation(int* a,int length)
{
int i,flag;
sort(a,a+length);
do
{
for(i=0;i<length;i++)
{
if(a[i]==3)
flag=1;
else if(a[i]==4) //假设3在4的左边,运行完代码,flag就是2
flag=2;
}
if(flag==1) //假设4在3的左边,运行完代码,flag就是1
{
for(i=0;i<length;i++)
cout<<a[i];
cout<<endl;
}
}while(next_permutation(a,a+length));
}
int main(void)
{
const int maxt=105;
int i,a[maxt],n;
cin>>n;//数组的元素个数
for(i=0;i<n;i++)
cin>>a[i];
printf("%d以内全部4在3左边的全排列结果为:\n",i);
permutation(a,n);
return 0;
}