题目:
Description:
输入一个整数n(1<=n<=8),输出1,2,...,n的全排列
Input:
3
Output:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Hint:
输出的顺序按第一个数从小到大排列,若第一个数相同,则按第二个数排列,依次类推。(使用递归)
解题代码如下:
//字典序列方法
#include <stdio.h>
int a[8],N;
void qsort(int a[],int left,int right);
int fac(); //求N的阶乘,即全排列的个数
void Reverse(int m,int n);
void Output();
void Fun();
int main()
{
int i;
scanf("%d", &N);
for (i = 0; i < N; ++i)
a[i] = i + 1;
qsort(a,0,N-1); //先将N个数排序
for (i = 0;i < N;i++)
{
printf("%d",a[i]);
if (i != N - 1)
printf(" ");
}
printf("\n");
Fun();
return 0;
}
void qsort(int a[], int left, int right) {
int i,j,temp;
i=left;
j=right;
temp=a[left];
if(left>right)
return;
while(i!=j) {
while(a[j]>temp &&j>i)
j--;
if(j>i)
a[i++]=a[j];
while(a[i]<temp &&j>i)
i++;
if(j>i)
a[j--]=a[i];
}
a[i]=temp;
qsort(a,left,i-1);
qsort(a,i+1,right);
}
//求N的阶乘,即全排列的个数
int fac() {
int count=1,i=2;
while (i<=N) {
count*=i;
i++;
}
return count;
}
void Reverse(int m, int n) {
int temp;
while (m<n) {
temp=a[m];
a[m]=a[n];
a[n]=temp;
m++;
n--;
}
}
void Output() {
int i;
for (i=0;i<N;i++) {
printf("%d",a[i]);
if (i != N-1)
printf(" ");
}
printf("\n");
}
void Fun() {
int index1, index2, i, k, min, n, temp; //index1为上述j下标,index2为上述k下标
n=fac();
//n次循环
for (k=1;k<n; k++) {
//求index1下标
for (index1=N-2; index1>=0; index1--) {
if (a[index1]<a[index1+1]) {
break;
}
}
min=32767;
//求index2
for (i=index1+1; i<N; i++) {
if (a[i]>a[index1]) {
if (a[i]<min) {
min=a[i];
index2=i;
}
}
}
temp=a[index1]; //交换a[index1],a[index2]
a[index1]=a[index2];
a[index2]=temp;
Reverse(index1+1,N-1); //逆置a[index1]到a[N-1]的数
Output(); //输出
}
}
参考方法一:
//递归方法
#include <stdio.h>
void permutation(int array[], int begin, int end) {
int i;
if(begin == end){
for(i = 0; i <= end; ++i){
printf("%d",array[i]);
}
printf("\n");
return;
} else {
//for循环遍历该排列中第一个位置的所有可能情况
for(i = begin; i <= end; ++i) {
swap(array[i], array[begin]);
permutation(array, begin + 1, end);
swap(array[i], array[begin]);
}
}
}
int main(int argc, char **argv) {
int a[3] = {1, 2, 3};
permutation(a, 0, sizeof(a) / sizeof(int) - 1);
return 0;
}
此方法可以通过递归得到所有的全排练,但顺序不是按照字典顺序排列;下面这个也是类似的方法;
全排列用的是 置换算法,
算法这东西重在理解。具体代码并不那么重要。
全排列是将一组数按一定顺序进行排列,如果这组数有n
个,那么全排列数为n!
个。现以{1, 2, 3, 4, 5}
为例说明如何编写全排列的递归算法。
1.首先看最后两个数4, 5
。 它们的全排列为4 5
和5 4
, 即以4
开头的5
的全排列和以5
开头的4
的全排列。由于一个数的全排列就是其本身,从而得到以上结果。
2.再看后三个数3, 4, 5
。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3
六组数。即以3
开头的和4,5
的全排列的组合、以4
开头的和3,5
的全排列的组合和以5
开头的和3,4
的全排列的组合.从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}
, 全排列为perm(p),pn = p - {rn}
。因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)
。当 n = 1
时 perm(p) = r1
。为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1
个数的全排列。
算法如下:
#include <stdio.h>
int n = 0;
void swap(int *a, int *b)
{
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int list[], int k, int m)
{
int i;
if(k > m)
{
for(i = 0; i <= m; i++)
printf("%d ", list[i]);
printf("\n");
n++;
}
else
{
for(i = k; i <= m; i++)
{
swap(&list[k], &list[i]);
perm(list, k + 1, m);
swap(&list[k], &list[i]);
}
}
}
int main()
{
int list[] = {1, 2, 3, 4, 5};
perm(list, 0, 4);
printf("total:%d\n", n);
return 0;
}
参考方法二:
//字典序列方法
#include <stdio.h>
int a[10], N;
void qsort(int a[],int left, int right)
{
int i, j, temp;
i=left;
j=right;
temp=a[left];
if(left>right)
return;
while(i!=j)
{
while(a[j]>temp &&j>i)
j--;
if(j>i)
a[i++]=a[j];
while(a[i]<temp &&j>i)
i++;
if(j>i)
a[j--]=a[i];
}
a[i]=temp;
qsort(a, left, i-1);
qsort(a, i+1, right);
}
int fac() //求N的阶乘,即全排列的个数
{
int count=1,i=2;
while (i<=N)
{
count*=i;
i++;
}
return count;
}
void Reverse(int m, int n)
{
int temp;
while (m<n)
{
temp=a[m];
a[m]=a[n];
a[n]=temp;
m++;
n--;
}
}
void Output()
{
int i;
for (i=0;i<N; i++)
{
printf("%3d",a[i]);
}
printf("\n");
}
void Fun()
{
int index1, index2, i, k, min, n, temp; //index1为上述j下标,index2为上述k下标
n=fac();
for (k=1;k<n; k++) //n次循环
{
for (index1=N-2; index1>=0; index1--) //求index1下标
{
if (a[index1]<a[index1+1])
{
break;
}
}
min=32767;
for (i=index1+1;i<N;i++) //求index2
{
if (a[i]>a[index1])
{
if (a[i]<min)
{
min=a[i];
index2=i;
}
}
}
temp=a[index1]; //交换a[index1],a[index2]
a[index1]=a[index2];
a[index2]=temp;
Reverse(index1+1,N-1); //逆置a[index1]到a[N-1]的数
Output(); //输出
}
}
int main()
{
int i;
while (printf("\n Please input N: “), scanf("%d",&N)!=EOF)
{
printf("Please input %d numbers:\n",N);
for (i=0;i<N; i++)
{
scanf("%d",&a[i]);
}
qsort(a,0,N-1); //先将N个数排序
printf("These numbers are: \n");
for (i=0;i<N; i++)
{
printf("%3d",a[i]);
}
printf("\n");
Fun();
}
return 0;
}
此方法可以由用户决定排序哪一个数的全排列,而且是按字典顺序排列!