对于我的编程语言类,我应该在Scheme中编写一个函数来反转列表而不使用预制的反向函数。到目前为止,我得到的是
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
我遇到的问题是,如果我输入一个列表,请说(a b c)
它会给我(((() . c) . b) . a)
。
如果没有多组括号和.
,我该如何获得干净的清单呢?
答案 0 :(得分:4)
您的实施问题是cons
没有收到列表作为其第二个参数,因此您正在构建的答案不是正确的列表,请记住:a正确的列表由cons
带有列表的元素构成,最后一个列表为空。
一种可能的解决方法是使用辅助函数在累加器参数中构建答案,cons
反向元素 - 顺便说一下,这个解决方案是尾递归的:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
答案 1 :(得分:1)
你到了一半。结果中元素的顺序是正确的,只需要修复结构。
您想要的是执行此转换:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
这很容易编码。我们可以立即获得临时值的car
和cdr
。在每个步骤中,下一个中间结果由(cons (cdr interim-value) interim-result)
构建,interim-result
作为空列表启动,因为这是我们在此构建的 - 列表:< / p>
(define (transform-rev input)
(let step ( (interim-value input) ; initial set-up of
(interim-result '() ) ) ; the two loop variables
(if (null? interim-value)
interim-result ; return it in the end, or else
(step (car interim-value) ; go on with the next interim value
(cons ; and the next interim result
(... what goes here? ...)
interim-result )))))
interim-result
充当累加器。这就是所谓的“累加器技术”。 step
表示使用“named-let”语法编码的循环步骤。
所以总体反向是
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
您是否可以调整transform-rev
以便能够接受原始列表作为输入,从而跳过reverseList
来电?您只需要更改数据访问部分,即如何获得下一个临时值,以及添加到中间结果中的内容。
答案 2 :(得分:1)
逐步浏览列表并继续将列表的汽车附加到递归调用。
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
答案 3 :(得分:0)
(define (my-reverse L)
(fold cons '() L)) ;;left fold