推荐的良心博文http://www.cnblogs.com/chenyg32/p/3646074.html
例:求数组array[6]={1,2,3,4,5,6}的全排列,并在控制台中以从小到大的顺序输出。
非递归方法:
分析:我们需要理解如何通过上一个数求下一个数,这是我们循环的前提。例如这里有数字串364521,很显然它的下一个数字串应该是365124。这里我们给出算下一个数的过程:
编号 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
数字 | 3 | 6 | 4 | 5 | 2 | 1 |
1)对于数字串364521,我们从右向左找到第一组值使得array[i-1] < array[i],那么这里我们找到了array[2] < array[3](4 < 5),那么我们记下array[i-1]=array[2]=4这个数,令num=4;
2)从右往左(范围为[i,5])找到第一个大于num的数字,我们找到数字array[k]=array[3]=5,那么我们将该数字与num互换,然后我们得到数字串:
编号 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
数字 | 3 | 6 | 5 | 4 | 2 | 1 |
3)然后我们将数组array[k~5]的位置的数倒置一下,得到数字串:
编号 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
数字 | 3 | 6 | 5 | 1 | 2 | 4 |
这样我们就得到了结果。
算法思想重点指导:
我们发现下标从i到5的数字是降序排列,所以相对于他们这几个数来说已经没有下一个数字串了,即相对于他们自己来说他们是“最大”的,所以只好往高位换数字。剩下的很容易,大家自己思考一下就得出结果了。
#include <stdio.h>
#define N 6
void swap(int *a,int *b){//交换数组中的两个数
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
int find(int *array,int num,int left){//从右向左找第一个大于num的数,返回该数的位置
int i;
for(i=N-1;i>=left;i--){
if(array[i]>num)
return i;
}
return -1;
}
void reverse(int * array,int start){//将数组从下标为start的地方开始到N-1的数字倒置
int end=N-1,tmp;
while(start<end){
tmp=array[end];
array[end]=array[start];
array[start]=tmp;
start++;
end--;
}
}
void Print(int * array){//输出数组array
int i;
for(i=0;i<N;i++)
printf("%d ",array[i]);
printf("\n");
}
int main(void){
int array[N]={1,2,3,4,5,6};
int i,num,k;
Print(array);
while(1){
//第一个for循环用来找num
for(i=N-1;i>0;i--){
if(array[i-1]<array[i])
break;
}
if(i==0)//如果发现现在数字串已经为最大的数(完全是从左到右的降序)那么break
break;
num=array[i-1];
k=find(array,num,i);
swap(&array[k],&array[i-1]);
reverse(array,i);
Print(array);
}
return 0;
}
递归方法
代码提示:我们这里用数组mark作为标记数组,result作为字符串的存储数组,x指的是result数组中还需要加几个数字便组成一个完整的字符串,例如result数组中已经为6543,那么还需要 加两个数字21或12即可组成654321或654312。
#include <stdio.h>
#include <memory.h>
#define N 10
#define n 4
int k;
void Print(int *result){
int i;
for(i=0;i<k;i++){
printf("%d ",result[i]);
}
printf("\n");
}
void f(int *mark,int *result,int x){
int i;
if(x==1){
for(i=1;i<=n;i++){
if(mark[i]==0){
result[k++]=i;
Print(result);
k--;
return;
}
}
}else{
for(i=1;i<=n;i++){
if(mark[i]==0){
mark[i]=1;
result[k++]=i;
f(mark,result,x-1);
k--;
mark[i]=0;
}
}
}
}
int main(void){
int mark[N],result[N];
k=0;
memset(mark, 0, sizeof(mark));
memset(result, 0, sizeof(result));
f(mark,result,n);
return 0;
}