【问题标题】:Defining a Tree in LISP (Racket)在 LISP (Racket) 中定义一棵树
【发布时间】:2020-03-13 04:11:52
【问题描述】:

我正在尝试使用 Racket 的#plai 语言定义一棵树,但在通过“添加节点”函数创建树时我有点挣扎。

我使用的定义类型是这样的:

(define-type BBT
  [empty]
  [leaf (elem number?)]
  [node (elem number?) (left BBT?) (right BBT?)])

我想构建一棵如下所示的树:

(node 3 (empty) (node 5 (leaf 4) (leaf 6)))

在这个电话之后:

(add-node 6 (add-node 4 (add-node 5 (add-node 3 (empty)))))

到目前为止,我已经尝试了以下方法:

(define (add-node n tree)
  (match tree
    [(empty) (node n (empty) (empty))]))

这适用于一棵空树,因为它只是在两侧添加了一个带有空树的节点,但我还没有找到一种方法来构建像我上面分享的示例那样的树。

关于我应该做什么的任何提示或建议?我知道当它捕获“节点”情况时我应该使用递归,但到目前为止我还没有想出成功的尝试。

谢谢!

【问题讨论】:

  • 在不引入诸如晦涩难懂的球拍语言之类的复杂事物的情况下,您是否了解它的工作原理?这个问题是关于递归还是球拍?
  • 您的add-node 严重不足:它添加了新的右分支、左分支还是什么?它是添加叶子的节点吗?它是否构造了一棵以现有树为分支之一的新树?如果有,是哪个分支?另一个分支是什么?

标签: lisp racket


【解决方案1】:

从你的例子:

(add-node 6 (add-node 4 (add-node 5 (add-node 3 (empty)))))

应该生产

(node 3 (empty) (node 5 (leaf 4) (leaf 6)))

这包含对add-node 的许多调用,这使它更加混乱。因此,为了更好地了解您想要什么,我将从最里面的add-node 调用开始。

(add-node 3 (empty))

从您问题中的初始代码来看,这似乎应该产生

(node 3 (empty) (empty))

所以现在替换你更大的例子中最里面的调用,它变成了

(add-node 6 (add-node 4 (add-node 5 (node 3 (empty) (empty)))))
=
(node 3 (empty) (node 5 (leaf 4) (leaf 6)))

现在我必须弄清楚下一个最里面的调用应该做什么。

(add-node 5 (node 3 (empty) (empty)))

在最终输出中,3 保持在顶部,5 转到正确的节点,所以我只能猜测这个调用应该会产生

(node 3 (empty) (node 5 (empty) (empty)))

现在替换更大示例中的调用:

(add-node 6 (add-node 4 (node 3 (empty) (node 5 (empty) (empty)))))
=
(node 3 (empty) (node 5 (leaf 4) (leaf 6)))

下一个最里面的调用是

(add-node 4 (node 3 (empty) (node 5 (empty) (empty))))

现在我不明白你的逻辑。按照前面示例的模式,4 应该进入最右边的节点“right-right”。但在这个例子中,它似乎进入了右节点的左边部分,“right-left”。它似乎没有去最近的空节点,这将是纯粹的“左”,所以我不知道你要制作什么模式。

如果您想要更好的答案,请澄清您的问题并添加更多细节。

【讨论】:

    【解决方案2】:

    最后,我找到了一种像这样构造树的方法:

    (define (add-node n tree)
      (match tree
        [(empty) (node n (empty) (empty))]
        [else (add-aux n tree)]))
    
    (define (add-node-aux n tree)
      (match tree
        [(empty) (leaf n)]
        [(leaf e) (if (> e n)
                      (node e (leaf n) (empty))
                      (node e (empty) (leaf n)))]
        [(node e l r) (if (> e n)
                        (node e (add-node-aux n l) r)
                        (node e l (add-node-aux n r)))]))
    

    它完成了这项工作,但我想知道是否有一种方法可以在不依赖辅助函数的情况下创建树。基本上,我创建了辅助调用以防止只有一个节点(根树)的树被标记为“叶子”。因此,不是让第一个元素输出形状为(叶子 3)的树,而是通过调用递归函数,可以获得类似(节点 3(空)(空))的树。

    有没有办法在不进行辅助调用的情况下做到这一点?

    谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2014-09-23
      • 2017-10-29
      相关资源
      最近更新 更多