输入正数n,按字典序从小到大的顺序输出n个数的所有排列。两个序列的字典序大小关系等价于从头开始第一个不相同位置处的大小关系。
一、生成1~n的排列
思路:
void print_permutation(序列A,集合S)
{
if ( S 为空 ) 输出序列 A;
else 按照从小到大的顺序依次考虑 S 的每个元素 v
{
print_permutation(在A的末尾添加v后得到的新序列,S-{v});
}
}
Code:
#include<stdio.h>
#include<stdlib.h>
void print_permutation(int n, int *A, int cur);
int A[10];
int main()
{
print_permutation(10,A,0);
system("pause");
return 0;
}
void print_permutation(int n, int *A, int cur)
{
if(cur==n)
{
for(int i=0;i<n;++i) printf("%d ",A[i]);
printf("\n");
}
else
for(int i=1;i<=n;++i)
{
int ok=1;
for(int j=1;j<cur;++j)
if(i==A[j]) ok=0;
if(ok)
{
A[cur]=i;
print_permutation(n,A,cur+1);
}
}
}
二、生成可重集的排列
在一的基础上,首先要对输入数组P进行排序;再者一中元素不重复而这里可以重复,要统计次数;第三,对于输入1 1 1,只输出一次而不是多次,即对连续的相同元素,不能多次出现。
Code:
#include<stdio.h>
#include<stdlib.h>
int cmp_int(const void *_a, const void *_b);
void print_permutation2(int n, int *P, int *A, int cur);
int P[]={1,2,3,3,2,1,4};
int A[7];
int main()
{
int n=7;
qsort(P,7,sizeof(P[0]),cmp_int);
print_permutation2(n,P,A,0);
system("pause");
return 0;
}
void print_permutation2(int n, int *P, int *A, int cur)
{
if(cur==n)
{
for(int i=0;i<n;++i) printf("%d ",A[i]);
printf("\n");
}
else
for(int i=0;i<n;++i)//遍历数组P的所有元素
if(!i||P[i]!=P[i-1])//连续的相同元素不枚举多次
{
int c1=0,c2=0;
for(int j=0;j<cur;++j) if(P[i]==A[j]) c1++;//P[i]在A数组中已出现的次数
for(int j=0;j<n;++j) if(P[i]==P[j]) c2++;//P[i]在P数组中共出现的次数
if(c1<c2)
{
A[cur]=P[i];
print_permutation2(n,P,A,cur+1);
}
}
}
int cmp_int(const void *_a, const void *_b)
{
return *(int*)_a - *(int*)_b;
}
三、下一个排列
C++的STL中一个库函数 next_permutation()
Code:
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int main()
{
int n,p[10];
scanf("%d",&n);
for(int i=0;i<n;++i) scanf("%d",&p[i]);
sort(p,p+n);
do
{
for(int i=0;i<n;++i) printf("%d ",p[i]);//输出排列p
printf("\n");
}while(next_permutation(p,p+n));
system("pause");
return 0;
}
测试STL next_permutation
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
char a[7]="aacdef";
do
{
cout<<a<<endl; //根据输出发现,没有重复序列
}while(next_permutation(a,a+6));
cout<<"permutation is over!"<<endl;
cout<<a<<endl;//输出最小序
int b[]={1,2,3};
cout<<b<<endl;//输出地址
system("pause");
return 0;
}
通过上面测试代码,可以知道,STL 中的 next_permutation 函数不会输出重复的排列。(相反,有些情况下重复的排列是需要的,这就需要考虑下了,不能直接用next_permutation 函数。)参考:刘汝佳《算法竞赛入门经典》