繁体   English   中英

反转列表错误

[英]Reversing a list error

我正在学习DrRacket,并且需要编写一个可以反转列表的程序。 我有下面的内容,它正反转数字,但是以某种方式将它们嵌套在列表或其他内容中。

(define (reverse-list lon)
  (if (empty? lon)
      empty
      (cons (reverse-list (rest lon))
            (cons (first lon)
                  empty))))

输出(反向列表(列表1 2 3 4)):

(list (list (list (list empty 4) 3) 2) 1)

有人知道为什么输出不只是一个列表吗?

谢谢您的帮助!

cons有两个单元格。 carcdr 单元格可以显示为(a . b) ,其中ab可以是任何值。

一对有另一种表示形式。 如果b是另一对或空白列表,则可以替换. b ) . b )b不带首字母(

(a . ())             ; ==> (a)
(a . (b . c))        ; ==> (a b . c)
(a . (b . (c . ()))) ; ==> (a b c)

现在为您的代码。 想象一下,您尝试使用(1 2 3 4) (或(1 . (2 . (3 . (4 . ()))))来进行尝试。 使用替换规则,我们可以精确地计算您的程序执行的操作:

(reverse-list '(1 . (2 . (3 . (4 . ())))))                   ; ==>
(if (empty? '(1 . (2 . (3 . (4 . ())))))
    empty 
    (cons (reverse-list (rest '(1 . (2 . (3 . (4 . ()))))))
          (cons (first '(1 . (2 . (3 . (4 . ()))))) 
                empty)))                                      ; ==>
(if #f
    empty 
    (cons (reverse-list (rest '(1 . (2 . (3 . (4 . ()))))))
          (cons (first '(1 . (2 . (3 . (4 . ()))))) 
                empty)))                                      ; ==>

(cons (reverse-list '(2 . (3 . (4 . ()))))
      (cons 1 empty))                                      ; ==>

(cons (cons (reverse-list '(3 . (4 . ())))
            (cons 2 empty))
      (cons 1 empty))                                      ; ==>

(cons (cons (cons (reverse-list '(4 . ()))
                  (cons 3 empty))
            (cons 2 empty))
      (cons 1 empty))                                      ; ==>

(cons (cons (cons (cons (reverse-list '())
                        (cons 4 empty))
                  (cons 3 empty))
            (cons 2 empty))
      (cons 1 empty))                                      ; ==>

(cons (cons (cons (cons '()
                        (cons 4 empty))
                  (cons 3 empty))
            (cons 2 empty))
      (cons 1 empty))                                      ; ==>

((((() . (4 . ())) . (3 . ())) . (2 . ())) . (1 . ()))     ; ==>
((((() . (4)) . (3)) . (2)) . (1))                         ; ==>
((((() 4) 3) 2) 1)

现在。 真实的反向列表将以点分符号显示如下:

(4 . (3 . (2 . (1 . ())))) ; ==> (4 3 2 1)

没有其他办法了。 您需要与cons非常亲密,并了解如何显示构造它们的不同方法。 提示是几乎每个列表都是从头到尾创建的,并从头到尾进行迭代。

很高兴看到您已经解决了自己的问题。 但是我觉得我应该选择一点,因为反向列表确实可以按照您的方式建立一个迭代列表。

(define (reverse-list lon)
  ;; iterative helper procedure
  (define (aux lon acc)
    (if (empty? lon)
        acc
        (aux (rest lon) 
             (cons (first lon) acc))))
  ;; use helper
  (aux lon empty))

(reverse-list '(1 2 3 4)) ; ==> (4 3 2 1)

如您所见,我们从头到尾进行迭代。 这样做,到目前为止,我们将当前元素限制为累积列表,并且该操作是从头到尾的。 Ei最后添加的元素将是结果中的第一个。 这样做的好处是,我们为每个处理的单元格使用一个新单元格,它已成为最终结果的一部分。 每次使用append您都将复制第一个参数,以便n元素列表获得(apply + (range n))不必要的单元分配。

经验更丰富的Schemer将使用命名的let来执行本地过程并一次调用:

(define (reverse-list lon)
  (let aux ((lon lon) (acc empty))
    (if (empty? lon)
        acc
        (aux (rest lon) 
             (cons (first lon) acc)))))

因此,最终的工作是将第一个弊端替换为附加项以停止列表嵌套。

(define (reverse-list lon)
  (if (empty? lon) empty (append (reverse-list (rest lon)) (cons (first lon) empty))))

问题已解决,不过感谢您的帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM