全排列
#include<iostream> //全排列的生成算法:字典序法,允许可重集
#include<algorithm>
using namespace std;
int num[10]={0,4,3,1,9,10},n;
void permutation()
{
int i,j,k;
sort(num+1,num+n+1);
while(1)
{
for(i=1;i<=n;++i)
cout<<num[i]<<" ";
cout<<endl;
for(i=n-1;i>=1;--i)
if(num[i]<num[i+1])
break;
if(i==0)
break;
int Min=100000;
for(j=i+1;j<=n;++j)
if(num[j]>num[i]&&num[j]<Min)
{
Min=num[j];
k=j;
}
swap(num[i],num[k]);
for(j=i+1;j<=(i+1+n)/2;++j)
swap(num[j],num[i+1+n-j]);
}
}
int main()
{
n=5;
permutation();
return 0;
}
/*
字典序算法如下:
比如 839647521 是数字1~9的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4 839647521
在该数字后的数字中找出比4大的数中最小的一个5 839647521
将5与4交换 839657421
将7421倒转 839651247
所以839647521的下一个排列是839651247
*/
递归生成不可重集的全排列
#include<iostream> //递归生成不可重集的全排列
#include<algorithm>
using namespace std;
int n,num[10]={0,23,2,10,7,9},arr[10]; //num[]是原始序列,arr记录全排列
void permutation(int id)
{
if(id==n+1)
{
for(int i=1;i<=n;++i)
cout<<arr[i]<<" ";
cout<<endl;
return ;
}
int i,j;
for(i=1;i<=n;++i) //尝试在arr[i]中填充num[1]-num[n]
{
int ok=1;
for(j=1;j<id;++j)
if(arr[j]==num[i]) //如果num[i]已经在arr[1]-arr[id-1]出现过,则不能再选
{
ok=0;
break;
}
if(ok==1)
{
arr[id]=num[i];
permutation(id+1);
}
}
}
int main()
{
n=5;
sort(num+1,num+n+1); //先排序
permutation(1);
return 0;
}
递归生成可重集的全排列(允许重复元素出现)
#include<iostream> //递归生成可重集的全排列(允许重复元素出现)
#include<algorithm>
using namespace std;
int n,num[10]={0,23,2,10,10,9},arr[10]; //num[]是原始序列,arr记录全排列
void permutation(int id)
{
if(id==n+1)
{
for(int i=1;i<=n;++i)
cout<<arr[i]<<" ";
cout<<endl;
return ;
}
int i,j;
for(i=1;i<=n;++i) //尝试在arr[i]中填充num[1]-num[n]
{
if(i==1||num[i]!=num[i-1]) //比如num[]={1,1,2};那arr[i]上只能放1和2,而不是1,1和2,其他位置也是同样
{
int c1=0,c2=0;
for(j=1;j<id;++j)
if(arr[j]==num[i])
c1++;
for(j=1;j<=n;++j)
if(num[j]==num[i])
c2++;
if(c1<c2) //统计num[1]-num[n]中num[i]出现的次数c1,和arr[1]-arr[id-1]中num[i]出现的次数c2,只要c1<c2,arr[id]上就能填充num[i]
{
arr[id]=num[i];
permutation(id+1);
}
}
}
}
int main()
{
n=5;
sort(num+1,num+n+1); //先排序
permutation(1);
return 0;
}