版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83315100
【问题】利用递归方法找出从自然数1,2,…,n中任取r个数的所有组合
【例如】n=5,r=3,所有组合为:
方法一
【思路】
- 抽象问题:1,…,n中选r --> f(n,r)
- 从边界n考虑,n要么取,要么不取 --> f(n,r) = f(n-1, r) + f(n-1, r-1)
- 退出条件:r==0时,就已经选完了
- 异常条件:n<r的时候
int a[50];
void f(int n,int r,int m) {
int i;
if (n<r) return ;
if (r==0) {
for (i=0; i<m; i++) printf("%d", a[i]);
printf("\n");
} else {
//选n
a[m] = n;
f(n-1, r-1, m+1);
//不选n
f(n-1, r, m);
}
}
方法二
【代码】
// 从1-n的数字中选r个数字
// 目前选的一个放入a[m]位置中
void C(int n, int r, int a[], int m) {
int i;
if (r==0) { //选完了
//输出
for (i=0; i<m; i++) printf("%d", a[i]);
printf("\n");
} else {
// 在[r,n]的范围内选一个数字放入a[m]
for (i=n; i>=r; i--) {
a[m] = i;
C(i-1, r-1, a, m+1);
}
}
}
【理解】用树状的形式输出递归树(先序)
树状的方式类似于这种https://blog.csdn.net/summer_dew/article/details/82937941
完整代码
方法一:
#include<stdio.h>
int a[50];
void f(int n,int r,int m) {
int i;
if (n<r) return ;
if (r==0) {
for (i=0; i<m; i++) printf("%d", a[i]);
printf("\n");
} else {
//选n
a[m] = n;
f(n-1, r-1, m+1);
//不选n
f(n-1, r, m);
}
}
int main() {
int n,r;
while (1) {
printf("输入n与r,空格分割\n>>> ");
scanf("%d%d", &n, &r);
f(n, r, 0);
printf("\n");
}
return 0;
}
方法二:
#include<stdio.h>
// 从1-n的数字中选r个数字
// 目前选的一个放入a[m]位置中
void C(int n, int r, int a[], int m) {
int i;
// 以树状输出递归树
/*
for (i=0; i<m; i++) {
printf(" ");
}
printf( "C(%d,%d, '" , n,r);
for (i=0; i<m; i++) {
printf("%d ", a[i]);
}
printf("', %d)",m );
printf("\n");
*/
if (r==0) { // 选完了
// 输出
for (i=0; i<m; i++) printf("%d", a[i]);
printf("\n");
} else {
// 在[r,n]的范围内选一个数字放入a[m]
for (i=n; i>=r; i--) {
a[m] = i;
C(i-1, r-1, a, m+1);
}
}
}
int main() {
int n,r;
int a[50];
while (1) {
printf("输入n与r,空格分割\n>>> ");
scanf("%d%d", &n, &r);
C(n, r, a, 0);
printf("\n");
}
return 0;
}