我是编程新手,很难理解递归。有一个问题我一直在努力,但无法弄清楚。我真的不明白它们是如何解决的。
“定义一个过程加上两个非负整数并返回它们的总和。你可以使用的唯一过程(除了递归调用加之外)是:零?,sub1和add1。
我知道这是一个内置函数的方案,所以我知道它们有可能解决,我只是不明白如何。递归是如此棘手!
任何帮助将不胜感激! =]谢谢
我正在使用Petite Chez Scheme(使用SWL编辑器)
答案 0 :(得分:4)
递归是软件开发中非常重要的概念。我不知道(petit chez)计划所以我将从一般角度来看待它。
递归函数的概念是一遍又一遍地重复相同的任务,直到达到某个限制边界。提出第一个问题,你有两个数字,你需要将它们加在一起。但是,您只能向数字添加1或从数字中减去1。您还有字面值零。
因此。将数字视为两个桶。它们每个都有10块石头。您想要将这两个桶“添加”在一起。你只允许一次移动一块石头(即你不能抓住一把石头或将一个水桶放到另一块石头上)。
假设您想要将左侧铲斗中的所有物品一次移动到右侧铲斗中。你打算做什么?
首先,您必须从左侧铲斗中取出1块石头,即您正在使用sub1
从铲斗中取出一块石头。然后将相同的石头添加到右侧桶中,即您add1
到右侧桶。
现在你可以循环执行此操作,但是你不知道在任何给定的解决方案中会有多少石头。你真正想要做的是说:“从左斗取一块石头,放入正确的水桶中,重复直到左水桶里没有石头。”左桶中没有石头的情况称为“基础案例”。这就是你说好的点,我现在已经完成了。
这种情况的伪代码示例是(使用你的加号,add1,sub1和零):
plus(leftBucket, rightBucket)
{
if(leftBucket == zero) // check if the left bucket is empty yet
{
// the left bucket is empty, we've moved all the stones
return rightBucket; // the right bucket must be full
}
else
{
// we still have stones in the left bucket, remove 1,
// put it in the right bucket, repeat.
return plus(sub1(leftBucket), add1(rightBucket));
}
}
如果你还需要更多的帮助,请告诉我,我可以通过其他例子来看看,这看起来可能是你的功课问题,而且递归对于理解非常重要所以我不想只是给你所有的答案。
答案 1 :(得分:2)
递归与归纳密切相关 - 首先解决(或证明)基本情况,然后假设您的解决方案对某些值 n 是正确的,并使用为 n + 1 解决(或证明)它。
所以这里的第一步是看第一个问题。将两个数字加在一起会有什么好的基本情况?
好吧,我们有基本情况:当其中一个数字为零时。
为简单起见,我们假设第二个数字为零,只是为了让事情变得更容易。
因此我们知道(+ n 0)
等于n
。现在,对于我们的递归步骤,我们想要进行任意调用(+ x y)
,然后将其转换为 close 到理想(+ n 0)
的调用。这样我们就会取得一些进展,并最终解决我们的问题。
那我们该怎么做?
(+ x y)
当然等同于(+ (add1 x) (sub1 y))
- 这使我们更接近(zero? y)
的基本情况。
这为我们提供了最终解决方案:
(define (+ x y)
(if (zero? y)
(x)
(+ (add1 x) (sub1 y))
))
(当然,您可以交换参数的顺序,它仍然是等效的。)
可以使用类似的机制来解决其他两个问题。
答案 2 :(得分:2)
递归只是一个调用自身的函数。最常见,易于理解的递归示例是走一个看起来像树的数据结构。
您如何访问树的每个分支?您将从主干开始并调用visit(branch),将树的树干作为第一个分支传递。 Visit()为每个分支的每个分支调用自己,依此类推。
public void visit(Branch branch)
{
// do something with this branch here
// visit the branches of this branch
foreach(var subbranch in branch.branches)
{
visit(subbranch)
}
}