Scheme 方案二叉搜索树

Scheme 方案二叉搜索树,scheme,racket,Scheme,Racket,我已经将助手函数定义为: ;; returns value of node (define (value node) (if (null? node) '() (car node))) ;; returns left subtree of node (define (left node) (if (null? node) '() (cadr node))) ;; returns right subtree of node (define (right node

我已经将助手函数定义为:

;; returns value of node
(define (value node)
  (if (null? node) '()
      (car node)))

;; returns left subtree of node
(define (left node)
  (if (null? node) '()
      (cadr node)))

;; returns right subtree of node
(define (right node)
  (if (null? node) '()
      (caddr node)))
我正在尝试编写一个函数
leaves
,它返回一个列表,列表中的叶子按从左到右的顺序排列

(define (leaves tree)
    (if (and (?null (left tree)) (?null (right tree)))
        ???
        (leaves (left tree)) (leaves (right tree))))
但这是我能做到的


例如:(leaves’(1(2())(3()))应该计算为’(23)

这看起来像是你在做的,但是如果你有两个子节点(或者只有一个子节点,如果你不想打印只有一个子节点),你就不打印自己了


我的目标是首先解决这个问题,然后将您的解决方案更改为该解决方案来解决这个问题。

在您目前所拥有的内容中,
将需要计算叶的值,即
(值节点)
,因为它是迭代的基本情况。此外,您还需要将从基本案例中获得的值组合到迭代案例中<当您需要组合多个结果时,code>list通常是一个很好的首选
cons
通常是我的第二次尝试。根据这些建议,您的
将离开
函数,如下所示:

(define (leaves tree)
    (if (and (null? (left tree)) (null? (right tree)))
        (value tree)
        (list (leaves (left tree)) (leaves (right tree)))))
当在您的
(leaves'(1(2()())(3()())
示例上运行时,它确实计算为
(23)

但是,;你还没做完!我们只使用1级递归进行测试。如果我们造一棵更大的树呢?类似于:
(leaves'(1(2(4())(5())(3(6())(7()(()))
运行此命令将提供
((4 5)(6 7))
。这些是顺序正确的正确值,但是我们有太多的结构,太多的括号。这是一个典型的问题,你会在你的计划职业生涯中遇到,所以让我解释一下为什么会发生这种情况,以及你如何着手解决这个问题

如果查看
If
表单的两个分支,您会注意到
(值树)
返回一个原子,或者在本例中返回一个数字。else分支获取两个
,并将其转换为
列表。我们将多次执行else分支——只要不在基本情况下。这意味着我们将继续包装,包装,包装成一个越来越深的列表结构。下面是我们要做的

让我们在基本情况下返回一个列表,在递归情况下保持列表平坦。在我们的基本情况下,要返回一个列表,只需返回
(列表(值树))
,而不仅仅是
(值树)
。在递归的情况下,我们需要一个函数,它接受两个列表并将它们组合在一起,而不生成更深的列表。确实存在这样一个函数-
append
。现在,让我们来看一下
留下的
函数:

(define (leaves tree)
        (if (and (null? (left tree)) (null? (right tree)))
            (list (value tree))
            (append (leaves (left tree)) (leaves (right tree)))))
间奏曲-测试用例

Racket有一个测试套件库,它有一个非常低的进入门槛,叫做。让我们在文件的底部放几个快速测试用例

(require rackunit)
;;empty tree
(check-equal? (leaves '()) '())

;;simple balanced tree
(check-equal?
 (leaves '(1 (2 () ()) (3 () ())))
 '(2 3))

;;larger balanced tree
(check-equal?
 (leaves '(1 (2 (4 () ()) (5 () ())) (3 (6 () ()) (7 () ()))))
 '(4 5 6 7))

;;unbalanced tree
(check-equal?
 (leaves '(1 (2 (4 () ()) ()) (3 () ())))
 '(4 3))
最近,racket增加了对测试子模块的支持和特定支持,如果您对这些子模块感兴趣并想了解它们的话


回到我们的问题上来。在运行测试时,我们注意到我们的函数在不平衡的树上表现不好。当我们有一个只有一片叶子的节点时,我们会得到额外的
()
s。这是因为当我们在一个不是叶子的节点上时,我们同时遍历左子树和右子树。我们真正需要的是
if
中的另外两个案例。我们可以嵌套
if
s,但是scheme的
cond
表单更有意义

现在,我们要填写的模板是:

(define (leaves tree)
  (cond [(leaf? tree) (...)]
    [(and (has-left? tree) (has-right? tree)) 
     (...)]
    [(has-left? tree) (...)]
    [(has-right? tree) (...)]
    [else (error "should never get here")]))

如果这是家庭作业,我就到此为止,让你满意地理解并解决剩下的问题。我希望我的解释为您提供了更多的方向,而不仅仅是“这是代码”的答案。

从定义树开始。你能为一棵树写下数据定义吗?否则,任何人都很难提供帮助。
(define (list-of-leaves tree)
  (if(leaf? tree)
     (list (node tree))
     (cond((right-branch-only? tree)(list-of-leaves (right-branch tree)))
          ((left-branch-only? tree)(list-of-leaves (left-branch tree)))
          (else(append (list-of-leaves (left-branch tree))
                       (list-of-leaves (right-branch tree)))))))