【问题标题】:Tree fold in Racket球拍中的树褶
【发布时间】:2021-02-07 01:10:36
【问题描述】:

我是 Racket 的初学者,我收到了这个问题:

  • 定义一个结构node,它具有以下字段:valueleftmiddleright。此结构表示树结构中的节点。
    这些字段包含存储在节点中的值,左子树, 分别是中间子树和右子树。如果一个子树 不存在,那么对应的字段应该包含一个 emptyNode 如下所述。
  • 定义一个结构emptyNode,以指定树中的一个空节点。
  • 编写一个函数treeFold,它接受一个函数f、一个初始值initial和一个树结构tree作为参数。这应该 然后产生一个值,这是使用 f 折叠的结果 树中的值(在其中使用 leftmiddleright 子树 命令)。请注意,f 是一个接受 两个 参数的函数。首先 参数是树中的一个值,第二个是部分 累积结果。

函数调用应该是:

(treeFold (lambda (a acc) (+ a acc)) 15 tree) 

树:

(node 7 (node 5 (emptyNode) (emptyNode) (emptyNode)) 
        (node 20 (emptyNode) (emptyNode) (emptyNode)) 
        (emptyNode))

输出:47

这是我到目前为止所做的:

(struct node (value left middle right) #:transparent)

(struct emptyNode () #:transparent)

(define tree 
    (node 7 
          (node 5 (emptyNode) (emptyNode) (emptyNode)) 
          (node 20 (emptyNode) (emptyNode) (emptyNode)) 
          (emptyNode)))

(define (treeFold f initial tree)
  (if (emptyNode? tree)
     (emptyNode)
     (node (f initial (node-value tree))
           (node-left tree)
           (node-middle tree)
           (node-right tree))))

我怎样才能得到整片叶子的总数?

任何想法或帮助,谢谢


编辑:因此,根据其 cmets 中的答案和讨论,我得到了一个新功能,但仍然存在错误,我找不到它。在这里:

(define (treeFold f initial tree) 
  (cond 
    [(emptyNode? tree) 
          (f initial 0)] 
    [else (f (node-value tree) 
             (f (treeFold f 
                   (treeFold f 
                      (treeFold f initial 
                         (node-left tree)) 
                      (node-middle tree)) 
                    (node-right tree))))]))

你能告诉我如何解决它吗?谢谢。


编辑:最终代码

(define (treeFold f initial tree) 
  (cond 
    [(emptyNode? tree) (f initial 0)] 
    [else (f  (node-value tree)                
              (treeFold f                   
                   (treeFold f 
                        (treeFold f initial 
                             (node-left tree)) 
                             (node-middle tree)) 
                             (node-right tree)))]))

它按我的预期工作

【问题讨论】:

  • 您的新代码仍有问题。正如我在答案中讨论的那样,collectAllStringsInWholeTree 将无法在其下工作。无需在空节点上将 initial0 组合在一起。为什么0?如果我们正在处理的是字符串怎么办?只需initial 就足够了。除此之外,做得很好。 :) 它定义了树的后序遍历,而我的回答建议使用前序遍历。我想两者都可以,因为要求中没有指定。但由于它被命名为“初始”,我希望预购是预期的。否则它会被命名为“final”之类的。
  • 带数字和+ 没关系,但如果是- 呢?或带有string-append 的字符串?那么一般来说,预折叠和后折叠的结果会有所不同。即(treeFold - 100 tree) 应该返回68,我认为。

标签: tree racket fold


【解决方案1】:

使用新版本的函数编辑问题后更新。

这是朝着正确方向迈出的一步。里面有一些正确的部分,也有一些不正确的部分。

函数就像可以连接在一起的盒子。东西在一些电线上进入,在其他一些电线上出去。每个盒子都有它正确的使用方式:电线的数量,以及它期望流入其中的东西。

您的新版本:

(define (treeFold f initial tree) 
  (cond 
    [(emptyNode? tree) 
          (f initial 0)] 
    [else (f (node-value tree)                 ;; (1)
             (f (treeFold f                    ;; (2)
                   (treeFold f 
                      (treeFold f initial 
                         (node-left tree)) 
                      (node-middle tree)) 
                    (node-right tree))))]))

f 需要两个参数。 (f initial 0) 看起来正确,至少在这方面。 (1) 的电话也是如此。但是在(2)f 的调用只向f 提供了一个参数,所以不可能是正确的。

接下来,到它的意思。对treeFold 的三个嵌套调用几乎正确:我们“进入”(node-left tree),即左子树,以initial 作为初始值,然后我们得到结果从中并使用 it 作为新的初始值进入中间子树,并使用计算结果遍历右子树。好的。我们完成了。这就是我们需要的最终结果——无需再将其输入f。因此,在对 treeFold 的三个嵌套调用之上的这两个对 f 的调用根本不需要。

除了,我们要如何处理(node-value tree)?它适合在哪里?答案是,它应该与initial 值结合,通过调用f 的方式,thatresult 应该作为初始值我们遍历 left 子树;我们开始折叠的值。

基本情况也不正确。我们已经有了initial,为什么要突然把它和0结合起来呢?为什么0?例如,我们可以折叠一棵包含 strings 的树,而将字符串与数字 0 组合起来没有多大意义。

不,0提供作为对treeFold 的调用的初始值,例如

(define (sumAllNumbersInWholeTree tree)
  (treeFold + 0 tree))

有了带弦的树,我们可以例如定义

(define (collectAllStringsInWholeTree tree)
  (treeFold string-append "" tree))

答案的初始版本如下。用你的新理解回顾一下它的(非常轻微的编辑)例子。 :)


对于

(define tree 
    (node 7 
          (node 5 (emptyNode) (emptyNode) (emptyNode)) 
          (node 20 (emptyNode) (emptyNode) (emptyNode)) 
          (emptyNode)))

根据规格,它必须是,

47 == (treeFold + 15 tree)
   == (treeFold + 15 
        (node 7 
          (node 5 (emptyNode) (emptyNode) (emptyNode)) 
          (node 20 (emptyNode) (emptyNode) (emptyNode)) 
          (emptyNode)))
   == (treeFold + 
          (treeFold + 
              (treeFold + (+ 15 7)
                  (node 5 (emptyNode) (emptyNode) (emptyNode)))
              (node 20 (emptyNode) (emptyNode) (emptyNode)))
          (emptyNode))
   == (treeFold + 
          (treeFold + 
              (treeFold +  
                   (treeFold + 
                       (treeFold + (+ 22 5) (emptyNode))
                       (emptyNode))
                   (emptyNode))
              (node 20 (emptyNode) (emptyNode) (emptyNode)))
          (emptyNode))
   == (treeFold + 
          (treeFold + 
              (treeFold +  
                   (treeFold + 27
                       (emptyNode))
                   (emptyNode))
              (node 20 (emptyNode) (emptyNode) (emptyNode)))
          (emptyNode))
   == (treeFold + 
          (treeFold + 
              (treeFold + 27
                   (emptyNode))
              (node 20 (emptyNode) (emptyNode) (emptyNode)))
          (emptyNode))
   == (treeFold + 
          (treeFold + 27
              (node 20 (emptyNode) (emptyNode) (emptyNode)))
          (emptyNode))
   .........

(写== 表示“等于”)。这已经为您提供了完整定义所需的一切,即

(treeFold + i (node v lt md rt))
==
(treeFold +
   (treeFold +
      (treeFold + (+ i v) lt)
      md)
   rt)

(treeFold + i (emptyNode))
==
i

【讨论】:

  • 你说的是 ``` (treeFold + i (node v lt md rt)) `` 会给出整个叶子的总和对吗?
  • 叶子都是空的,叶子中没有值。 treenodes 中的值总和为 32。(treeFold + 15 tree) 返回 47。
  • 首先您需要修正treeFold 的定义。这是各种各样的错误。使其遵循此答案底部的两条规则。
  • 对不起,我的问题不清楚。我的意思是包括根在内的整棵树的总数。根据问题,treeFold 函数应如下所示。所以根据该函数,即使它与我的不同,我如何使用 fold 来查找值的总和?
  • 你的树开始。你需要 32。(treeFold + 15 tree) 返回 47。为什么? (- 47 32) 是什么? (treeFold + 14 tree) 会返回什么?你应该怎么打电话才能得到 32?相同的调用会在任何tree 上工作,而不仅仅是你的树?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多