我目前正在学习Scheme并且刚刚学习了归纳集和递归。我目前定义了一个数据类型bTree,它是一个二叉树
(define-datatype bTree bTree?
(leaf
(datum number?))
(node
(value symbol?)
(left bTree?)
(right bTree?)))
哪个工作正常。我想创建一个函数,当给定bTree时,会返回从根(也是列表)到每个叶子的路径列表,其中左边用0表示,右边用1表示。 / p>
(define bTree-path
(lambda (tree)
(cases bTree tree
(leaf (datum) '())
(node (value left right)
(list (cons 0 (bTree-path left)) (cons 1 (bTree-path right)))))))
我的思维过程是,如果它看到一个叶子,它就不会返回当前列表。但是,如果它是节点,则会创建新列表。在此列表中,左右子树的递归调用函数,cons运算符分别为0和1(意味着在左侧步骤和右侧一步)。这很快被证明是错误的,因为测试树包含嵌套列表的结果。结果应该类似于((0 1)(0 0)(1)),这意味着有三个叶子可以通过向左,向左,向右或向左两次找到。
从叶子到根的工作将不起作用,因为您不知道叶子是左叶还是右叶。每次找到节点时调用列表都会导致嵌套。有没有一种方法可以使用左右子树的两个递归调用同时简单地调用两个列表?可能是功能还是操作?
答案 0 :(得分:0)
由于(bTree-path left)
的结果是(或至少应该是)该子树中从left
到树叶的所有路径的列表,因此您需要添加0
每条路径。
同样适用于正确的子树。
对列表的每个元素执行某些操作的函数是map
:
(map (lambda (path) (cons 0 path)) (bTree-path left))
接下来,您要将两个路径列表(从左侧和右侧)合并到一个列表中,执行该操作的函数是append
。
将所有这些放在一起作为练习。