反转列表错误

时间:2014-10-17 23:50:09

标签: list debugging racket reverse

我正在学习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)

任何人都知道为什么输出不是一个列表?

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

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

对一个替代表示。如果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 . ())))))进行尝试。使用substitution rules,我们会准确计算您的过程的作用:

(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非常亲密,并且知道如何显示构建它们的不同方法。一个提示是,几乎每个列表都是从结尾到开头创建的,并从开始到结束迭代。

答案 1 :(得分:1)

很高兴看到你解决了自己的问题。但是我觉得我应该选择一点,因为反转列表实际上正在迭代建立一个。

(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)

正如您所看到的,我们从头到尾进行迭代。正如我们所做的那样,到目前为止,我们将当前元素包含在累积列表中,并且该操作从头到尾。 E.I.最后添加的元素将是结果中的第一个元素。关于这一点的好处是我们为每个处理过的细胞使用一个新细胞,它成为最终结果的一部分。对于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)))))

答案 2 :(得分:0)

所以,最终工作的只是用附加替换第一个缺点来阻止列表嵌套。

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

问题解决了,感谢你的帮助。