首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SICP -练习2.27 -颠倒列表和子列表的要素

SICP -练习2.27 -颠倒列表和子列表的要素
EN

Code Review用户
提问于 2016-01-05 16:07:26
回答 2查看 564关注 0票数 2

来自SICP

练习2.27:修改练习2.18的深度反转过程,生成一个以列表作为参数并返回其值的深-深-反向过程,并返回其元素深反转的列表,以及所有深-深-反的子列表。例如,(定义x(列表(列表12)(列表3 4)) x((12) (3 4) )(深反向x) ((3 4) (1 2)) (深深反向x) ((4 3) (2 1))

请检查我的密码。

代码语言:javascript
复制
(define (deep-deep-reverse lst)
    (cond ((null? lst) '())
        ((list? lst) (append (deep-deep-reverse (cdr lst)) (list (deep-deep-reverse (car lst)))))
    (else lst)))

我花了一个小时来做这件事,实际上我对这段代码到底有多小感到非常惊讶。如何改进这段代码?也许能让它更快?

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-01-06 00:32:01

如果您实际上是这样缩进的,请使用一个自动的编辑器--通常cond的个别情况应该对齐,例如:

代码语言:javascript
复制
(define (deep-deep-reverse lst)
  (cond
   ((null? lst) '())
   ((list? lst) (append (deep-deep-reverse (cdr lst))
                        (list (deep-deep-reverse (car lst)))))
   (else lst)))

功能看起来不错。为了清晰起见,将中间的情况移到末尾也许是有意义的,但这并没有多大变化。

但是,考虑到以这种方式使用的append相当昂贵,因为它反复重新创建一个“长”列表(来自cdr递归),以便将“短”列表(来自car部分)放在末尾。

(作为读者的练习),您可以使用累加器来完全避免append (而cons就足够了)。这个函数看起来非常相似:

代码语言:javascript
复制
(define (deep-deep-reverse2 lst)
  (define (aux lst acc)
    ...)
  (aux lst '()))
票数 1
EN

Code Review用户

发布于 2016-01-06 02:31:14

如前所述,追加的开销很大,时间和内存约束行与第一个参数的大小相同。实际上,当输入是列表列表的列表时,在列表的每个cdr上重复出现的函数使得整个函数n^2。

要记住的另一件事是那份名单?也需要时间线性时间来完成。(导致另一个n^2时间约束。)另外一对?在固定时间内运行,但不保护/保护不受正确列表的影响。(然而,当您担心输入不当时,您应该继续在函数开始时检查它。)

您也可以通过在列表上折叠cons来反转列表。

代码语言:javascript
复制
(define (deep-deep-reverse3 x)
    (fold (lambda (x acc) 
            (cons (if (pair? x)
                      (deep-deep-reverse3 x)
                      x)
                  acc))
          '()
           x))
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/115907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档