输入n个整数,然后输出其全排列,如输入:3,输出:1 2 3 ,1 3 2 ,2 1 3 , 2 3 1 , 3 1 2 ,3 2 1.
递归解法:
思想:如2,3的全排列是以2开头的3的全排和以3开头2的全排,1,2,3的全排列是以1开头2 ,3的全排,以2开头1,3的全排和以3开头1,2的全排 。如此就可以用递归了。
#include<stdio.h>
#include<stdlib.h>
void print(int *a , int length)
{
int i;
for(i = 0 ; i<length ; i++)
{
printf("%d " , a[i]);
}
printf("\n");
}
void swap(int *k , int *l)
{
int temp;
temp = *k;
*k = *l;
*l = temp;
}
void sort(int *a , int k , int length)
{
if(k>=length -1)
{
print(a , length);
}
else
{
int i ;
for(i = k ; i < length ; i++)
{
swap(&a[k] , &a[i]); //进入下一层前交换,求以a[i]开头的全排
sort(a , k+1 , length); //递归进入下一层
swap(&a[k] , &a[i]); //递归完后返回上一层时要恢复递归前的位置顺序
}
}
}
int main()
{
int n , i ;
scanf("%d" , &n);
int *a = (int*)malloc(sizeof(int)*n);
for(i = 0 ; i < n ; i++)
{
a[i] = i+1;
}
int length = n;
sort(a , 0 , length);
return 0;
}
个人认为一个可以用递归解决的问题一般主要考虑两点:从递归的第一层到第二层的过程和递归结束的过程。上面的问题还要考虑从递归的下一层返回到上一层前,需要恢复上一层的状态。
非递归解法:
思想:设数组长度为length,每次从右往左找到第一个下降的数(即a[i]>a[i-1]的a[i-1],令这个i-1等于k,记下k),再从右往左找到第一个大于a[k]的数记为a[m],交换a[k],a[m]的值,然后把下标为k+1到length-1的数值交换,即a[k+1]和a[length-1]交换,a[k+2]和a[length-2]交换,a[k+...]和a[length-...]交换.到最后一个排列是由大到小排列,如1,2,3的最后一个排列是3,2,1.找不到下降的数了,寻找过程终止。
#include<iostream>
using namespace std;
void print(int a[] , int g)
{
for(int i = 0 ; i<g ; i++)
cout<<a[i]<<" ";
cout<<endl;
}
void swap(int *a , int i , int j)
{
int temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
int main()
{
int n , i;
cin>>n;
int *a = new int[n];
for(i = 0 ; i<n ; i++)
{
a[i] = i+1;
}
int k , g = n;
bool ok = true;
print(a , g);
while(ok)
{
int i;
for(i=g-1; i>0; i--)
if(a[i]>a[i-1])
{
k = i-1; //寻找第一个下降的数
for(int j=g-1; j>0; j--) //交换
if(a[j]>a[k])
{
swap(a,j,k);
int n = g;
while(k<n)
{
k++;
n--;
if(k<=n) swap(a,k,n);
}
print(a , g); 交换后打印
break;
}
break; //重新从右往左找
}
if(i==0) ok = false; //i==0说明找不到下降的数了
}
return 0;
}
8404

被折叠的 条评论
为什么被折叠?



