在弄清楚这个算法的递归版本后,我试图创建一个迭代(尾递归)版本。
我非常接近,但返回的列表最终会被撤消。
这是我到目前为止所做的:
(define (first-n-iter lst n)
(define (iter lst lst-proc x)
(cond
((= x 0) lst-proc)
(else (iter (cdr lst) (cons (car lst) lst-proc) (- x 1)))))
(if (= n 0)
'()
(iter lst '() n)))
即。致电(first-n-iter '(a b c) 3)
将返回(c b a)
。
有人会建议修复吗?再一次,我想保留尾递归。
注意:我希望你不建议只在返回的列表上调用(reverse lst)
。
答案 0 :(得分:1)
你可以做头部哨兵技巧来实现尾递归模数缺点
(define (first-n-iter lst n)
(define result (cons 'head '()))
(define (iter tail L-ns x)
(cond
((= x 0) (cdr result))
((null? L-ns)
(error "FIRST-N-ITER input list " lst " less than N" n))
(else
(begin (set-cdr! tail (list (car L-ns)))
(iter (cdr tail) (cdr L-ns) (- x 1))))))
(iter result lst n))
(first-n-iter '(a b c d e f g h i j k l m n o p q r s t u v w x y z) 8))
;Value 7: (a b c d e f g h)
还添加了一个cond子句来捕获您尝试获取的元素多于列表中实际存在的元素。
答案 1 :(得分:0)
您可以翻转cons
语句的参数,list
最后一个(先前的第一个)参数,并将cons
更改为append
(define (first-n-iter lst n)
(define (iter lst acc x)
(cond
[(zero? x) acc]
[else (iter (cdr lst) (append acc (list (car lst))) (sub1 x))]))
(iter lst empty n))
将按您的意愿工作。如果你把它作为一个学习练习,那么我认为这就是你所需要的。但是如果你真的想要发挥这个功能,你应该知道它已经完成 - (take lst 3)
此外,您根本不需要if
声明 - 您对(= x 0)
的检查会立即返回'()
,然后您将(iter lst '() n)
传递给它是。因此,(if (= n 0) ... )
正在开展(cond [(= x 0)...)
'已为您做的工作。