1. 设计一个算法并编程实现,将一个正整数划分成多个正整数的加和,并把所有的结果组合输出。
分 析: 正整数的划分就是把一个正整数n,写成多个大于等于1且小于等于其本身的整数的和,其中各加数所构成的集合为n的一个划分,这是一个典型的递归算法。即:
一个正整数被划分成多个正整数,划分组合的成员个数最多是这个正整数的大小,最少是这个正整数本身。而且在递归的过程中还要传递上层的划分数字,要求划分的后一个数字大于等于前一个,使无序的划分方式变为有序,去掉重复项。
代码实现:
#include <stdio.h>
int mark[10]; //定义全局变量
int n;
void Divide(int now,int k,int pre){
int i;
if(now>n) return;
if(now==n){
for(i=0;i<k-1;i++)
printf("%d+",mark[i]);
printf("%d\n",mark[i]);
}
else{
for(i=pre;i>0;i--){
if(i<=pre){
mark[k]=i;
now+=i;
Divide(now,k+1,i); //递归调用函数
now-=i;
}
}
}
}
int main(void){
scanf("%d",&n);
Divide(0,0,n-1);
return 0;
}
运行结果:
2. 设计一个算法并编程实现,对一组数的全排列,并将所有的排列结果输出。
分 析 : 对于全排列问题,f(n)=n!(定义0!=1),其中需要用到函数的递归调用,在调用中,序列中的某两个元素需要不断地交换位置,在输出时调用一次,满足条件即可输出,是一种情况。一组数的全排列组合的个数为n!,通过先序递归将这一组数存入新的数组中,递归的过程中需要判断新放入的数在数组中是不是存在,如果存在,就不能被放入数组中,如果不存在,则可以放入数组,递归一次,在数组中放入一个数。递归四次则输出一次,输出完成后递归回退,进行穷举。R的全排列可归纳定义如下:
当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;
当n>1时,Perm(R)由(r1)Perm(R1),(r2)Perm(R2),......,(rn)Perm(Rn)构成。
代码实现:
#include <stdio.h>
#define N 100
void swap(int *a, int *b){ //功能:交换两个数
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int arr[], int k, int m){
int i,n=0;
if(k > m){
for(i = 0; i <= m; i++)
printf("%d ", arr[i]);
printf("\n");
n++;
}
else{
for(i = k; i <= m; i++){
swap(&arr[k], &arr[i]);
perm(arr, k + 1, m); //递归调用
swap(&arr[k], &arr[i]);
}
}
}
int main(void){
int n,i,k;
int arr[N];
printf("请输入有几个数:\t");
scanf("%d",&n);
for(i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
perm(arr, 0, n-1);
return 0;
}
运行结果: