Data structures 方案中树的深度反转(Lisp)

Data structures 方案中树的深度反转(Lisp),data-structures,tree,lisp,scheme,reverse,Data Structures,Tree,Lisp,Scheme,Reverse,我对Scheme中的基本树数据结构有一个很深的反向 (define (deep-reverse t) (cond ((null? t) '()) ((not (pair? t)) t) (else (cons (deep-reverse (cdr t)) (deep-reverse (car t)))))) (define stree (cons (list 1 2) (list 3 4))) 1 ]=> (deep-reverse stree)

我对Scheme中的基本树数据结构有一个很深的反向

(define (deep-reverse t)
  (cond ((null? t) '())
        ((not (pair? t)) t)  
        (else (cons (deep-reverse (cdr t)) (deep-reverse (car t))))))

(define stree (cons (list 1 2) (list 3 4)))
1 ]=> (deep-reverse stree)
;Value: (((() . 4) . 3) (() . 2) . 1)
我觉得自己像个清洁工,更好的结果是:

(4 3 (2 1))
有没有人能提供一些指导,说明我的深度反转功能哪里出了问题?谢谢。

试试这个:

(define (deep-reverse t)
  (let loop ((t t)
             (acc '()))
    (cond ((null? t) acc)
          ((not (pair? t)) t)
          (else (loop (cdr t)
                      (cons (loop (car t) '()) acc))))))
可以这样称呼:

(define stree (cons (list 1 2) (list 3 4)))
(deep-reverse stree)
> (4 3 (2 1))
要创建反向列表,一种技术是将答案累积到参数中(我通常称之为
acc
)。由于我们在列表上操作,因此必须在列表的
car
cdr
部分调用递归。最后,我使用命名let作为避免创建额外函数的简写,但通过使用两个参数(树和累加器)定义辅助函数也可以获得相同的结果:

(define (deep-reverse t)
  (aux t '()))

(define (aux t acc)
  (cond ((null? t) acc)
        ((not (pair? t)) t)
        (else (aux (cdr t)
                   (cons (aux (car t) '()) acc)))))

最好将任务拆分为简单的操作,而不是一次完成所有操作。您想要实现的可以这样描述:反转当前列表本身,然后深度反转其中的所有子列表(或者反过来说,这两个步骤的顺序并不重要。我选择这个顺序是因为它可以更好地格式化源代码)

现在,标准库中已经有一个函数可以简单地反转列表,
reverse
。因此,您需要做的就是将其与作为子列表的元素上的递归结合起来:

(define (deep-reverse t)
  (map (lambda (x)
         (if (list? x)
             (deep-reverse x)
             x))
       (reverse t)))

我认为最好根据元素计数反转列表: 空列表是反向的,单元素列表也是反向的,超过1个元素是尾和头的反向串联

(defun deep-reverse (tree)
   (cond ((zerop (length tree)) nil)
         ((and (= 1 (length tree)) (atom (car tree))) tree)
         ((consp (car tree)) (append (deep-reverse (cdr tree)) 
                                     (list (deep-reverse (car tree)))))
         (t (append (deep-reverse (cdr tree)) (list (car tree))))))

以下几点对我很有用:

(定义(深层反向树)
(定义(深反向iter项目acc)
(续)
((空?项)acc)
((非(成对项目))项目)
(else)(深反向iter
(cdr项目)
(cons(深倒车(汽车项目))附件
(深逆iter树())
(定义x(列表(列表12)(列表34(列表56)))
(新行)
(显示(深反转x))
它按预期打印
((6 5)4 3)(2 1))
,并使用最少的标准库函数:
pair?
检查树是否为
cons
null?
检查空树/列表

树的此解决方案是列表的
reverse
函数的推广:

(定义(反向项目)
(定义(反向iter项目acc)
(续)
((空?项)acc)
((非(成对项目))项目)
(其他(反向iter(cdr项目)(cons(car项目)acc‘‘‘‘‘)’)
(与国际热核实验堆项目()相反)

区别在于
深倒车
也适用于
汽车项目

啊,谢谢。我试图尽可能避免使用库函数(不知道这是否是一个好主意),但在Scheme中反转列表是我所知道的事情。您介意解释一下代码吗?我想如果我研究它,我会理解的,但这对我来说还不是直观的。答案中已经有了解释。我猜您可能还不知道:
map
将函数应用于列表的每个元素,并在新列表中返回结果
lambda
定义了一个匿名函数。@zallaak不要回避基本列表处理库;发现使用it的机会与任何事情一样重要。使用通用实用程序函数是正确的方法,如果你没有学会使用它们,那么你就是在做错误的事情,没有库函数的解决方案是不必要的难以编写和阅读的。但是,您可以做的是,首先尝试编写您自己版本的库函数。在这种情况下,您可以像Rörd那样解决原始问题,然后作为附加练习,编写自己的
map
reverse
实现。感谢您的解释。我还不熟悉loop,您已经为我提供了一些很酷的函数。