【问题标题】:Scheme find far left node of a tree recursively方案递归查找树的最左侧节点
【发布时间】:2020-05-29 19:40:52
【问题描述】:
我正在编写一个函数来查找任何树中最左边的节点。该函数不遍历树或给出最左边的节点,而只给出第一个节点的最左边的子节点。
(define (far-left tree)
(cond (null? (cadr tree))
(car tree)
(far-left (cdr tree))))
样本输入,它提供了许多节点而不是所需的节点:
(display (far-left '(1 (3 4 (6 7 (12 13))) 8 9 (10 11))))
【问题讨论】:
标签:
recursion
tree
scheme
racket
【解决方案1】:
你所说的“第一个节点的最左边的孩子”是(cadr tree)。
您的函数中有一个 (cadr tree),这表明第一个条件始终为真。
这就是正在发生的事情。
cond的形式是
(cond clause-1 clause-2 ...)
每个子句依次具有(condition value) 的形式。
也就是说,
(cond (condition-1 value-1)
(condition-2 value-2)
(condition-3 value-3)
...)
如果你将它与你的函数相匹配,你会看到
-
null? 是 condition-1 和 (cadr tree) 是 value-1,
-
car 是 condition-2 和 tree 是 value-2,并且
-
far-left 是 condition-3 和 (cdr tree) 是 value-3。
由于null? 不是#f,所以总是选择第一个子句。
正确的形式是
(define (far-left tree)
(cond
((null? (cadr tree)) (car tree))
(else (far-left (cdr tree)))
不过,这段代码仍然不起作用。
修复作为练习留下的错误。
【解决方案2】:
数据定义:Tree
-
Tree 是 Leaf 或 Node,其中:
-
Leaf 是Number。
-
Node 是子Trees 的非空列表。
函数:far-left
-
条件 1:
Leaf 作为输入无效,因为我们应该在任何树中找到“最左边的节点。
-
条件 2:如果
Node 将 Leaf 作为其最左侧(或 first)元素,则它是最左侧节点。如果最左边的元素是 Tree 而不是 Leaf,我们会重复它。
#lang typed/racket
(define-type Leaf Number)
(define-type Node (Pairof Tree (Listof Tree)))
(define-type Tree (U Leaf Node))
(: far-left (-> Tree Node))
(define (far-left tree)
(cond [(number? tree) (error "Farthest left node of a leaf does not exist!")]
[(cons? tree) (if (number? (first tree)) tree (far-left (first tree)))]))
测试:
(far-left '(1 (3 4 (6 7 (12 13))) 8 9 (10 11)))
; => '(1 (3 4 (6 7 (12 13))) 8 9 (10 11))
(far-left '((3 4 (6 7 (12 13))) 1 8 9 (10 11)))
; => '(3 4 (6 7 (12 13)))
(far-left '(((6 7 (12 13)) 3 4) 1 8 9 (10 11)))
; => '(6 7 (12 13))
(far-left '((((12 13) 6 7) 3 4) 1 8 9 (10 11)))
; => '(12 13)