从网上down的例子,来自于:http://www.dayi.net/CExcellent/39108.asp,不得不说,递归真是没学好。弄了半天,终于给弄明白了,程序的意思。下面就分析下:
m表示,当前已经挑的个数。初始为0.
n表示当前挑的值可从n开始。
k表示要挑选的个数,程序一开始就确定的。那么k-m表示,还有几个没有挑。因为程序是从1...n,开始的。k-m的值也可以表示,挑的值的下限。如从1...5之间挑选 k=3,m=1,这表示,第一位已经挑选过,第二位最小是2,因为要保留一个1,给最后一位。
关于递归的分析,最好可以画个图。
#include<stdio.h>
#include<malloc.h>
#include <stdlib.h>
void combination(int n, int m);
int k,*a;
void main()
{
int n;
printf("Input n and k: ");
scanf("%d%d",&n,&k);
a=(int*)malloc(sizeof(int)*k);
combination(n,0);
system("pause");
}
void combination(int n,int m)
{
int i;
if(m<k)
{
for(i=n;i>=k-m;i--) //首先这个for循环很重要,再次,k-m的控制是很合理的。
{
a[m]=i;
combination(i-1,m+1);
}
}
else
{
for(i=0;i<k;i++)
printf("%d ",a[i]);
printf("\n");
}
}
在论坛里看到的一种解法:似乎更加容易理解些,但是,是有问题的。就是对于一些下限的处理,如第一个数5,第二个数是1,那么第三个数怎么取呢?根据程序,可以知道,当第三个数<1时,本次递归就结束了。不输出而已,也是可以的,但感觉不如在程序中加入了判断,更觉得程序完整。程序如下:
#include<cstdio>
#include<deque>
#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;
deque<int> result;
void solve(int n, int k) {
if(result.size() < k) {
for(int m = n; m >= 1; --m) {
result.push_back(m);
solve(m - 1, k);
result.pop_back();
}
} else {
copy(result.begin(), result.end(), ostream_iterator<int>(cout));
cout << endl;
}
}
int main(int argc, char *argv[]) {
int n, k;
scanf("%d%d", &n, &k);
solve(n, k);
return 0;
}