2个尾部递归函数的长度[球拍]

时间:2012-10-10 03:30:53

标签: scheme racket

我正在尝试编写两个单独的尾递归函数来计算列表的长度,并且我给出了这些限制:

  1. 编写一个尾递归的版本lengtht,并根据需要使用外部(非嵌套)辅助功能

  2. 编写第二个版本,lengtht2,不使用其他顶级函数。该函数仍然应该是尾递归的,并且可以使用您想要的任何本地绑定

  3. 我是新手,我理解尾递归的一般形式是:

    (define (func x)
        (cond (end-test-1 end-value-1)
              (end-test-2 end-value-2)
              (else (func reduced-x))))
    

    我对如何做到这一点感到有点困惑

2 个答案:

答案 0 :(得分:2)

本质上,尾递归函数会一直调用自身直到达到最终状态。然而,与“常规”递归不同,它将中间答案传递给自身,直到它到达结尾。

一个例子是:

(define (find-length i lst)
  (if
    (null? lst) i
    (find-length (+ i 1) (cdr lst))))

该函数有两个值:i,它跟踪到目前为止列表的长度,lst,我们计算的元素列表。ii,就所有意图和目的而言,是我们对列表中元素的运行计数。因此,如果我们调用此方法,我们将要将null?初始化为0来调用它。

首先,我们检查列表是否为空。 (i)如果列表为空,我们可以假设我们已经计算了所有元素,因此我们只返回find-length,这是我们的运行计数。这是我们的最终条件。

否则,我们再次致电i。但是,这一次,我们将(cdr lst)加1,并从列表(find-length 0 (list 2 3 4 3 5 3)) 中删除了第一个元素。

例如,假设我们调用这样的函数:

(find-length 1 '(3 4 3 5 3))
(find-length 2 '(4 3 5 3))
(find-length 3 '(3 5 3))
(find-length 4 '(5 3))
(find-length 5 '(3))
(find-length 6 '()) ; end condition, return 6

在我们评估时,程序会递归调用:

{{1}}

This question通常是尾递归的一个很好的参考。

答案 1 :(得分:2)

这看起来像是家庭作业,所以我会给你一些提示,指出你正确的方向,你可以填补空白。试试第一个问题:

(define (loop lst acc)              ; receives a list and an accumulator
  (cond ((null? lst) <???>)         ; if the list is empty return the accumulator
        (else (loop <???> <???>)))) ; advance the recursion, +1 to accumulator

(define (length1 lst)
  (loop <???> <???>))               ; how should we initialize the iteration?

尝试第二个问题:

(define (length2 lst)
  (letrec ((loop <???>)) ; lambda with the same procedure as the previous `loop`
    (loop <???> <???>))) ; start the recursion exactly the same as in `length1`

无论如何,想一想:空(空)列表的长度是多少?答案将向您展示如何初始化迭代。对于这两种解决方案,我们使用一个名为acc的额外参数来跟踪到目前为止的答案,并将它与列表一起传递给循环尾递归过程。