在Scheme中编写尾递归take过程:将获取列表前n项函数转换实现
Scheme尾递归版take函数实现
你现有代码的问题
- 终止条件错误:数值参数
n不能用null?判断,应该判断n是否减到0,或者输入列表是否已经为空 - 缺少结果累加逻辑:你没有把遍历到的前n个元素保存下来,迭代过程中只遍历了列表没有生成结果
- 初始参数传值错误:调用内部迭代器时你传了初始值
0,而非外层接收到的参数n
正确实现代码
我们用一个累加器acc来保存已经收集到的元素,因为Scheme里列表从头部拼接效率更高,最后返回前把累加器反转就能得到正序的前n个元素:
(define (take n items) ;; 内部尾递归迭代器,acc是累加器存储已收集的元素 (define (iter remaining items acc) (cond ;; 终止条件1:已经取够n个元素,返回反转后的累加器(恢复正序) ((= remaining 0) (reverse acc)) ;; 终止条件2:列表已经遍历完毕,返回反转后的累加器 ((null? items) (reverse acc)) ;; 尾递归调用:剩余要取的数量减1,列表取cdr,把当前头部元素拼到累加器 (else (iter (- remaining 1) (cdr items) (cons (car items) acc))))) (iter n items '()))
测试用例验证
运行你的测试代码:
(take 4 '(1 2 3 4 5))
得到的输出为 (1 2 3 4),符合预期。如果输入列表长度小于n,比如(take 10 '(1 2 3)),会返回原列表(1 2 3),和原有非尾递归版本的行为完全一致。
内容的提问来源于stack exchange,提问作者N.A.
相关产品推荐
相关产品推荐

