【问题标题】:Racket: tail recursion on list outputs a reversed list球拍:列表上的尾递归输出反向列表
【发布时间】:2017-09-23 18:49:20
【问题描述】:

我希望我的函数对给定列表中的每个数字求平方,如果 lst 中的元素是一个列表,该函数递归地应用于它并对该列表的元素进行操作。

这是我的代码:

(define (sqr-up-rec-tail lst)
  (define (helper lst newlist)
    (if (null? lst) newlist
      (if (list? (car lst))
          (helper (cdr lst) (cons (sqr-up-rec-tail (car lst)) newlist))
          (helper (cdr lst) (cons (* (car lst) (car lst)) newlist)))))
  (helper lst ()))

我的函数有效,但是,我得到了一个反向平方列表。 例如,当我运行时:

(sqr-up-rec-tail '(2 4 6 (10 20)))

我得到的输出是:

((400 100) 36 16 4)

我想不使用使用外部反向功能获得正确的输出。我的猜测是我应该使用 append 而不是 cons,虽然我没有让它工作。

谢谢。

【问题讨论】:

  • 只需将...if (null? lst) newlist... 更改为...if (null? lst) (reverse newlist)...
  • @Renzo "我想在不使用外部反向函数的情况下得到正确的输出。"

标签: list recursion scheme racket tail-recursion


【解决方案1】:

append 可以工作,但请记住,这会使您的函数花费 O(n²) 时间,因为 append 基本上是这样的:

(define (append a b)
  (if (null? a)
      b
      (cons (car a)
            (append (cdr a) b))))

因为append 是一个糟糕的 O(n) 时间和空间。它将使您的结果算法在 O(n²) 时间和空间上使用它,因为您将它用于每个子列表直至结果的完整列表。

既然你已经有了一个助手,你可以用它来制作你自己的reverse

(define (reverse-helper from to)
  (if (null? from)
      to
      (reverse-helper (cdr from) (cons (car from) to))))

而不是返回(helper lst '()) 的结果,而是使用(reverse (helper lst '()) '())

【讨论】:

    【解决方案2】:

    在这里使用尾递归的问题是,第一个被处理的元素最终成为 newlist 中的最后一个元素,因此需要像 appendreverse 这样的过程。您可以通过避免尾递归来不使用使用appendreverse 构造过程,如下所示:

    (define (map-sqr lst)
      (cond
        [(null? lst) empty]
        [(pair? (car lst))
         (cons (map-sqr (car lst))
               (map-sqr (cdr lst)))]
        [else
         (cons (* (car lst) (car lst))
               (map-sqr (cdr lst)))]))
    

    但是,如果你必须使用尾递归,那么正如你所说,append 可以在累加时使用以获得所需的输出,如下所示:

    (define (map-sqr-tail lst)
      (let loop ([lst lst]
                 [new-lst '()])
        (cond
          [(null? lst) new-lst]
          [(pair? (car lst))
           (loop (cdr lst)
                 (append new-lst (list (loop (car lst) empty))))]
          [else
           (loop (cdr lst)
                 (append new-lst (list (* (car lst) (car lst)))))])))
    

    两种实现都按预期工作:

    > (map-sqr '(2 4 6 (10 20 (30))))
    '(4 16 36 (100 400 (900)))
    > (map-sqr-tail '(2 4 6 (10 20 (30))))
    '(4 16 36 (100 400 (900)))
    

    【讨论】:

      猜你喜欢
      • 2012-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 2021-04-24
      • 1970-01-01
      相关资源
      最近更新 更多