我正在尝试撤消列表,这是我的代码:
(define (reverse list)
(if (null? list)
list
(list (reverse (cdr list)) (car list))))
所以,如果我输入(反向'(1 2 3 4)),我希望它出来(4 3 2 1),但现在它不给我那个。我做错了什么,我该如何解决?
答案 0 :(得分:13)
重复列表的自然方式不是解决此问题的最佳方法。使用append
,正如@lancery指出的接受的答案中所建议的那样,也不是一个好主意 - 无论如何,如果你在Scheme中学习你的方式,那么如果你试图自己实现解决方案,我会告诉你该做什么,但首先是一个提示 - 不要使用list
作为参数名称,这是一个内置程序,你将覆盖它。使用其他名称,例如lst
。
通过辅助程序反转列表更简单,该程序累积了结果的 head 中每个元素的结果,这将产生反转列表的效果 - 顺便提一下,辅助程序是尾递归的。这是一般的想法,填补空白:
(define (reverse lst)
(<???> lst '())) ; call the helper procedure
(define (reverse-aux lst acc)
(if <???> ; if the list is empty
<???> ; return the accumulator
(reverse-aux <???> ; advance the recursion over the list
(cons <???> <???>)))) ; cons current element with accumulator
当然,在现实生活中,你不会从头开始实现reverse
,因此有一个内置的procedure。
答案 1 :(得分:2)
使用名为let
的尾递归方法:
(define (reverse lst)
(let loop ([lst lst] [lst-reversed '()])
(if (empty? lst)
lst-reversed
(loop (rest lst) (cons (first lst) lst-reversed)))))
这与在Oscar的答案中使用带有累加器参数的辅助函数的方法基本相同,其中loop
之后的let
绑定使得let成为内部函数,你可以调用
答案 2 :(得分:2)
这是一个递归过程,它描述了在Scheme中反转列表的迭代过程(尾递归)
(define (reverse lst)
(define (go lst tail)
(if (null? lst) tail
(go (cdr lst) (cons (car lst) tail))))
(go lst ())))
使用替代模型(反向(清单1 2 3 4))
;; (reverse (list 1 2 3 4))
;; (go (list 1 2 3 4) ())
;; (go (list 2 3 4) (list 1))
;; (go (list 3 4) (list 2 1))
;; (go (list 4) (list 3 2 1))
;; (go () (list 4 3 2 1))
;; (list 4 3 2 1)
这是一个递归过程,描述了在Scheme中反转列表的递归过程(不是尾递归)
(define (reverse2 lst)
(if (null? lst) ()
(append (reverse2 (cdr lst)) (list (car lst)))))
(define (append l1 l2)
(if (null? l1) l2
(cons (car l1) (append (cdr l1) l2))))
使用替换模型(reverse2(list 1 2 3 4))
;; (reverse2 (list 1 2 3 4))
;; (append (reverse2 (list 2 3 4)) (list 1))
;; (append (append (reverse2 (list 3 4)) (list 2)) (list 1))
;; (append (append (append (reverse2 (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (append (reverse2 ()) (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (append () (list 4)) (list 3)) (list 2)) (list 1))
;; (append (append (append (list 4) (list 3)) (list 2)) (list 1))
;; (append (append (list 4 3) (list 2)) (list 1))
;; (append (list 4 3 2) (list 1))
;; (list 4 3 2 1)
答案 3 :(得分:0)
以下是使用build-list
程序的解决方案:
(define reverse
(lambda (l)
(let ((len (length l)))
(build-list len
(lambda (i)
(list-ref l (- len i 1)))))))
答案 4 :(得分:0)
这个有效,但它不是尾递归过程:
(define (rev lst)
(if (null? lst)
'()
(append (rev (cdr lst)) (car lst))))
答案 5 :(得分:0)
我认为最好使用append代替cons
(define (myrev l)
(if (null? l)
'()
(append (myrev (cdr l)) (list (car l)))
)
)
这个带尾递归的另一个版本
(define (myrev2 l)
(define (loop l acc)
(if (null? l)
acc
(loop (cdr l) (append (list (car l)) acc ))
)
)
(loop l '())
)
答案 6 :(得分:0)
尾递归解决方案:
(define (reverse oldlist)
(define (t-reverse oldlist newlist)
(if (null? oldlist)
newlist
(t-reverse (cdr oldlist) (cons (car oldlist) newest))))
(t-reverse oldlist '()))
答案 7 :(得分:-1)
(define reverse?
(lambda (l)
(define reverse-aux?
(lambda (l col)
(cond
((null? l) (col ))
(else
(reverse-aux? (cdr l)
(lambda ()
(cons (car l) (col))))))))
(reverse-aux? l (lambda () (quote ())))))
(reverse? '(1 2 3 4) )
另一个与奥斯卡相似的答案。我刚开始学习计划,请原谅我,以防你发现问题:)。
答案 8 :(得分:-1)
实际上没有必要用一堆lambda追加或填充身体。
(define (reverse items)
(if (null? items)
'()
(cons (reverse (cdr items)) (car items))))