Racket:列表上的尾递归输出反向列表

时间:2017-04-26 11:31:20

标签: list recursion scheme racket tail-recursion

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

这是我的代码:

select e1.* from emp e1  inner join (select max(sal) avg_sal,dept_id from emp group by dept_id) as e2 on e1.dept_id=e2.dept_id and e1.sal=e2.avg_sal

我的功能有效,但是,我得到一个反转的平方列表。 例如,当我跑:

  

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

我得到的输出是:

  

((400 100)36 16 4)

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

感谢。

2 个答案:

答案 0 :(得分:3)

append可以工作,但请记住,因为追加基本上是你的函数O(n²)时间:

(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 '()) '())

答案 1 :(得分: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)))