我无论如何也无法想象递归及其作用。我对此很困惑。在竞技程序员手册中,我发现以下C++代码片段是解决以下问题的解决方案:
考虑生成一个包含n个元素的集合的所有子集的问题。 例如,{0,1,2}的子集有:;, {0}, {1}, {2}, {0,1}, {0,2}, {1,2} 和 {0,1,2}。
遍历集合的所有子集的一个优雅方法是使用递归。 下面的函数search生成集合{0,1,...,n-1}的子集。 函数维护一个向量subset,其中将包含每个子集的元素。搜索从参数0调用函数开始。
当函数search以参数k被调用时,它决定是否将元素k包含在子集中,如果是,在这两种情况下都会使用参数k + 1调用自身。但是,如果k = n,则函数注意到所有元素都已处理完毕,并且已生成了子集。
void search(int k) {
if (k == n) {
// process subset
} else {
search(k+1);
subset.push_back(k);
search(k+1);
subset.pop_back();
}
}
所以,确实,这个函数是有效的,我亲手测试了三次并且它完美地工作了。但是为什么呢?
除非我能记住所有递归问题的解决方案,否则我永远无法想出这种解决方案。在这里做了什么样的抽象化?使用了哪些更一般的概念?
我一直很难理解递归,所以任何帮助都将不胜感激。谢谢。
k == n
成立,那么我们可以对这个向量(以及每个子集的元素)进行任何操作。我认为不应该过多地解读它。 - herophantU
{a1, 所有子集(a2,...,an)},其中U
是集合并运算符。这是一个递归定义,因为所有子集的定义是以它自己为基础定义的。现在,这段代码相当直接地对该定义进行了翻译。你不理解的问题是你看不出这个定义在数学上是正确的吗?还是你不明白这段代码如何捕捉这个定义的呢? - john