6

我正在尝试反转列表,这是我的代码:

(define (reverse list)
  (if (null? list) 
     list
      (list (reverse (cdr list)) (car list))))

所以如果我输入 (reverse '(1 2 3 4)),我希望它显示为 (4 3 2 1),但现在它没有给我那个。我做错了什么,我该如何解决?

4

10 回答 10

13

遍历列表的自然方式并不是解决此问题的最佳方式。正如@lanceryappend指出的已接受答案中所建议的那样,使用 也不是一个好主意-无论如何,如果您正在学习 Scheme 中的方式,最好自己尝试实现该解决方案,我会告诉您该怎么做,但首先提示 - 不要list用作参数名称,这是一个内置过程,您会覆盖它。使用其他名称,例如,lst

通过辅助过程来反转列表更简单,该辅助过程在结果的头部累积每个元素的结果,这将具有反转列表的效果 - 顺便说一下,辅助过程是尾递归的。以下是总体思路,请填空:

(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从头开始实现,有一个内置的过程

于 2013-02-25T00:16:19.903 回答
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 成为您可以调用的内部函数。

于 2014-10-17T04:02:26.770 回答
2

这是一个递归过程,描述了在 Scheme 中反转列表的迭代过程(尾递归)

(define (reverse lst)
  (define (go lst tail)
    (if (null? lst) tail
        (go (cdr lst) (cons (car lst) tail))))
  (go lst ())))

使用替换模型 (reverse (list 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)
于 2017-02-14T21:43:33.670 回答
0

这是使用build-list过程的解决方案:

(define reverse
  (lambda (l)
    (let ((len (length l)))
      (build-list len
                  (lambda (i)
                    (list-ref l (- len i 1)))))))
于 2013-03-01T10:10:19.097 回答
0

这个可行,但它不是尾递归过程:

(define (rev lst)
 (if (null? lst)
     '()
      (append (rev (cdr lst)) (car lst))))
于 2014-04-06T07:33:18.447 回答
0

尾递归解:

(define (reverse oldlist)
    (define (t-reverse oldlist newlist)
        (if (null? oldlist)
            newlist
            (t-reverse (cdr oldlist) (cons (car oldlist) newest))))
    (t-reverse oldlist '()))
于 2021-02-18T20:29:49.597 回答
0

只需使用 cons 将列表折叠起来:

(define (reverse list) (foldl cons null list))

这也很有效,因为 foldl 是尾递归的,不需要追加。这也可以无点完成(使用球拍中的咖喱):

(define reverse (curry foldl cons null))
于 2021-09-10T23:06:47.630 回答
-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) )

还有一个类似于奥斯卡的答案。我刚刚开始学习计划,如果您发现问题,请见谅:)。

于 2014-02-03T17:17:14.313 回答
-1

我认为使用 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 '())
)
于 2015-01-04T19:33:22.453 回答
-1

实际上不需要用一堆 lambda 附加或填充主体。

(define (reverse items)
  (if (null? items)
      '()
      (cons (reverse (cdr items)) (car items))))
于 2014-10-16T19:25:49.233 回答