【问题标题】:Simple Recursion?简单递归?
【发布时间】:2011-02-18 03:16:19
【问题描述】:

我是编程新手,很难理解递归。有一个问题我一直在研究,但无法弄清楚。我真的只是不明白它们是如何解决的。

“定义一个过程 plus,它接受两个非负整数并返回它们的和。您可以使用的唯一过程(除了递归调用 plus)是:zero?、sub1 和 add1。

我知道这是方案中的内置函数,所以我知道它们可以解决,我只是不明白如何解决。递归太难了!

任何帮助将不胜感激! =] 谢谢

我在 Petite Chez Scheme 中工作(使用 SWL 编辑器)

【问题讨论】:

标签: recursion scheme


【解决方案1】:

递归是软件开发中一个非常重要的概念。我不知道 (petit chez) 方案,所以我将从一般的角度来处理这个问题。

递归函数的概念是一遍又一遍地重复相同的任务,直到达到某个限制边界。回答你的第一个问题,你有两个数字,你需要把它们加在一起。但是,您只能将数字加 1 或从数字减 1。您的文字值也为零。

所以。将您的数字视为两个桶。他们每个人都有10块石头。您想将这两个存储桶“添加”在一起。您一次只能移动一块石头(即您不能抓一把或将一个桶倒进另一个桶)。

假设您想将所有东西从左桶移到右桶,一次一块石头。你要做什么?

首先,您必须从左桶中取出 1 块石头,即您正在使用sub1 从桶中取出一块石头。然后,您将相同的石头添加到右侧的桶中,即您 add1 到右侧的桶中。

现在您可以循环执行此操作,但您不知道在任何给定解决方案中会有多少石头。你真正想做的是说“从左边的桶里取出一块石头,把它放在右边的桶里,然后重复,直到左边的桶里没有石头。”左桶中没有石头的这种情况称为“基本情况”。这就是你说好的,我现在完成了。

这种情况的伪代码示例是(使用您的 plus、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)); 
  }
}

如果您仍然需要更多帮助,请告诉我,我可以浏览其他示例,但这看起来可能是您的家庭作业问题,并且递归非常重要,因此我不想只给您所有答案。

【讨论】:

  • 哇,谢谢你的例子!我总是难以简化问题并找到递归步骤,但这确实帮助了我。我很感激
  • @Michele Degges 没问题,令人惊讶的是有多少专业开发人员不了解递归,所以这绝对不是一个简单的概念。当我第一次遇到它时,我自己也在挣扎,但最终它只是点击了。
【解决方案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)
    }
}

【讨论】:

    【解决方案3】:

    递归与归纳密切相关 - 首先您解决(或证明)一个基本情况,然后假设您的解决方案对于某个值 n 是正确的,然后使用为 n + 1 解决(或证明)它。

    所以这里的第一步是看第一个问题。将两个数字相加的最佳基本情况是什么?


    好的,所以我们有了基本情况:当其中一个数字为零时。

    为简单起见,我们假设第二个数字为零,只是为了让事情更容易一些。

    所以我们知道(+ n 0) 等于n。所以现在对于我们的递归步骤,我们想要任意调用(+ x y),并将其转换为更接近我们理想(+ n 0) 的调用。这样我们就会取得一些进展并最终解决我们的问题。

    那么我们要怎么做呢?


    (+ x y) 当然等同于(+ (add1 x) (sub1 y)) - 这使我们更接近我们的基本情况(zero? y)

    这给了我们最终的解决方案:

    (define (+ x y)
      (if (zero? y)
        (x)
        (+ (add1 x) (sub1 y))
    ))
    

    (当然,您可以交换参数的顺序,它仍然是等效的)。

    可以使用类似的机制来解决其他两个问题。

    【讨论】:

    • 我目前得到的是:如果 n1 为零,则返回 n2,如果 n2 为零,则返回 n1。我认为这些将是基本情况。
    • @Michele:添加了第二部分。从这里到哪里?
    • 谢谢伙计。我能够使用存储桶示例弄清楚它。我的基本情况是,如果 n1 为零,则返回 n2,然后从 n1 (递归)sub1 并将 1 添加到 n2,直到 n1 变为零。 :]
    • @Michele:听起来你现在明白了 :)
    • @Michele Degges 如果我的例子有帮助,如果你要取消接受的答案标记,至少要投票。
    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 2015-01-10
    • 2013-11-13
    相关资源
    最近更新 更多