一:全排列生成
一:没有重复元素的排列
1:非字典序的全排列生成:
思路:用DFS, 通过每次交换两个元素来生成
void swap(int &a, int &b)
{
int temp;
temp=a; a=b; b=temp;
}
void perm(int num[], int s, int e)//生成num[s,e]的所有排列
{
int i;
if( s==e )//当只剩下一个元素,
{
for(i=0; i<=e; i++)
cout<<num[i]<<" ";
cout<<endl;
}
else//还有多个元素未排列, 递归产生排列
{
for(i=s; i<=e; i++)
{
swap(num[s], num[i]);
perm(num, s+1, e);
swap(num[s], num[i]);
}
}
}
2:字典序全排列的生成
方法一:递归
#include<stdio.h>
bool used[10]={0};
int n, a[10], b[10];
void Perm(int m)
{
int i;
if( m == n)
{
for(i=0; i<n; i++)
printf("%d", b[i]);
printf("\n");
return;
}
for(i=0; i<n; i++)
{
if( !used[i] )
{
used[i]=1;
b[m]=a[i];
Perm(m+1);
used[i]=0;
}
}
}
int main()
{
int i;
scanf("%d", &n);
for(i=0; i<n; i++)
a[i]=i+1;
Perm(0);
}
方法二:非递归,此方法也适用于元素多次出现的重复排序
void Perm(int a[], int n)//非递归:注意a[n]的下标不能从0开始
{
int flag=0, min, pos, temp;
int i;
for(i=1; i<=n; i++)
printf("%d", a[i]);
printf("\n");
while( 1 )
{
flag=0;
for(i=n-1; i>=1; i--)//从右到左找到第一个小于右邻数的数a[flag]
{
if( a[i+1]>a[i])
{
flag=i;//这是原因,
break;
}
}
if( !flag ) break;
min=999;
for(i=n; i>flag; i--)//在flag-n中找到比a[flag]大的最小的数
{
if( a[i]>a[flag] && a[i]<min)
{
min=a[i];
pos=i;
}
}
temp=a[pos]; a[pos]=a[flag]; a[flag]=temp;
sort(a+flag+1, a+n+1);
for(i=1; i<=n; i++)
printf("%d", a[i]);
printf("\n");
}
}
方法三:用STL提供的函数
#include<iostream>
#include<algorithm>
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()
{
char str[] = "acb";
permutation(str,3);
return 0;
}
二:有重复元素的全排列生成
方法一:递归
#include<iostream>//非递归
#include<algorithm>
#include<cstdio>
using namespace std;
int a[10], used[10]={0}, num[10], record[10];
char b[10];
//将相同元素合并;用used[i]来记录数num[i]的个数;返回不同数字的个数
int Handle(int n )
{
int i, j;
num[0]=a[1];
j=0;
used[0]=1;
for(i=2; i<=n; i++)
{
if( a[i]==num[j])
used[j]++;
else
{
j++;
num[j]=a[i];
used[j]=1;
}
}
return j+1;//返回不同数字的个数
}
void Perm(int n, int m, int l)//递归
{
int i;
if( l==n )
{
for(i=0; i<n; i++)
printf("%d", record[i]);
printf("\n");
return;
}
for(i=0; i<m; i++)
{
if( used[i]>0 )
{
used[i]--;
record[l]=num[i];
Perm(n, m, l+1);
used[i]++;
}
}
}
int main()
{
int n, m;
int i, j, k;
cin>>n;
for(i=1; i<=n; i++)
{
cin>>b[i];
a[i]=b[i]-'0';
}
sort(a+1, a+n+1);
cout<<"递归:"<<endl;
m=Handle(n);
cout<<m<<endl;
Perm(n,m, 0 );
}
方法二:非递归
2:生成字典序排列的第二种方法即是