【问题标题】:Exercise 310. "How to Design Programs"练习 310 “如何设计程序”
【发布时间】:2016-03-24 20:58:15
【问题描述】:

我会很感激这个练习。 练习 310. 按顺序设计函数。它消耗一棵二叉树并生成树中所有 ssn 编号的序列,因为它们在查看树图时从左到右显示。

我的解决方案只是将每个左节点与节点下方的内容反转,然后访问右节点。虽然顺序是正确的,但答案的格式不正确。这是我的代码:

(define-struct no-info [])
(define NONE (make-no-info))

(define-struct node [ssn name left right])
; A BinaryTree (short: BT) is one of:
; – NONE
; – (make-node Number Symbol BT BT)

(define nine9 (make-node 99 "nine9" NONE NONE))
(define one0 (make-node 10 "one0" NONE NONE))
(define two4 (make-node 24 "two4" NONE NONE))
(define one5 (make-node 15 "one5" one0 two4))
(define seven7 (make-node 77 "seven7" NONE NONE))
(define nine5 (make-node 95 "nine5" NONE nine9))
(define two9 (make-node 29 "two9" one5 one8))
(define eight9 (make-node 89 "eight9" seven7 nine5))
(define six3 (make-node 63 "six3" two9 eight9))

; BT -> list
; produce the sequence of ssn numbers from left to right
(define (inorder bt)
  (cond
    [(no-info? bt) '()]
    [else (append (reverse (cons (node-ssn bt) (list (inorder (node-left bt)))))
                  (inorder (node-right bt)))]))

这是我运行(inorder six3)时的结果 (list (list (list () 10) 15 '() 24) 29) 63 (list '() 77) 89 '() 95 '() 99)

【问题讨论】:

    标签: functional-programming racket


    【解决方案1】:

    您的代码中有许多奇怪的元素。我希望inorder 会返回一个列表,但你仍然在 consing 之前将结果打包到列表 (list (inorder (node-left bt)) 中。这是你得到一堆嵌套列表的唯一原因。

    为什么反过来呢?树中的每个级别都会得到一个部分列表,您可以将其反转。然后根据树的高度是奇数还是偶数来确定顺序。

    鉴于inorder 递归实际上返回(10 15 24 29)(77 89 95 99) 你这样做(append (reverse (cons 63 (list '(10 15 24 29)))) '(10 15 24 29)) 这将导致((10 15 24 29) 63 77 89 95 99) 但当然递归并没有真正返回这些列表,因为它也会生成一个嵌套列表等等。

    如果你有两个列表和一个元素,并且你需要那个元素在中间,你可以这样做(append (10 15 24 29) (list 63) (77 89 95 99))

    现在有一个更好的方法来做到这一点:

    (define (tree->list tree (acc '()))
      (if (tree-null? tree)
          acc
          (tree->list (node-left tree)
                      (cons (node-ssn tree)
                            (tree->list (node-right tree) acc)))))
    

    在应用程序之前,需要计算它的参数,因此首先完成(tree->list (node-right tree) acc)。它将为您的树提供(77 89 95 99),对于一个具有一个ssn 和两个空节点的节点,它将是'()。然后ssn 被限制在右侧。然后它将充当左侧递归的累加器。

    由于从末尾到开头使用cons 制作了一个列表,这就是程序执行它的顺序,因此不需要append``and certainly no need forreverse`。

    【讨论】:

    • 谢谢。我应该提到这个问题给出了以下提示:Hint Use append,它像这样连接列表:(append (list 1 2 3) (list 4) (list 5 6 7)) == (list 1 2 3 4 5 6 7)
    【解决方案2】:

    在阅读了一些资料后,我想到了这个:

    ; BT -> list
    ; produce the sequence of ssn numbers from left to right
    (define (inorder bt)
      (cond
        [(no-info? bt) '()]
        [else (append (inorder (node-left bt)) (list (node-ssn bt))
                      (inorder (node-right bt)))]))
    

    一个术语列表并不那么优雅。不过效果很好。

    或者这个:

    ; BT -> list
    ; produce the sequence of ssn numbers from left to right
    (define (inorder bt)
      (cond
        [(no-info? bt) '()]
        [else (append (add-to-end (inorder (node-left bt)) (node-ssn bt))
                      (inorder (node-right bt)))]))
    
    (define (add-to-end ls ssn)
      (cond
        [(empty? ls) (cons ssn '())]
        [else (cons (first ls) (add-to-end (rest ls) ssn))]))
    

    【讨论】:

      猜你喜欢
      • 2012-05-09
      • 1970-01-01
      • 2010-12-28
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多