Tree 在Scheme中的二叉树的所有节点上筛选相同索引?
这开始是对SICP中练习2.29的误解,后来成为了个人的好奇心。这似乎很简单,我感到很尴尬,因为我很难找到一个适用于所有情况的解决方案。显然,我知道如何计算树上的节点数,以及如何将每个节点中的值枚举到一个列表中,但这两种算法都不能帮助我筛选每个节点中的相同索引 给定任何表示为嵌套列表的二叉树,其中每个节点持有一个或两个整数,应该有一个函数在每个节点中返回第一个值的列表,还有一个函数在每个节点中返回第二个值(请记住,并非所有节点都有第二个值) 以下是我到目前为止通过一个简单的测试用例得到的结果:Tree 在Scheme中的二叉树的所有节点上筛选相同索引?,tree,scheme,lisp,binary-tree,sicp,Tree,Scheme,Lisp,Binary Tree,Sicp,这开始是对SICP中练习2.29的误解,后来成为了个人的好奇心。这似乎很简单,我感到很尴尬,因为我很难找到一个适用于所有情况的解决方案。显然,我知道如何计算树上的节点数,以及如何将每个节点中的值枚举到一个列表中,但这两种算法都不能帮助我筛选每个节点中的相同索引 给定任何表示为嵌套列表的二叉树,其中每个节点持有一个或两个整数,应该有一个函数在每个节点中返回第一个值的列表,还有一个函数在每个节点中返回第二个值(请记住,并非所有节点都有第二个值) 以下是我到目前为止通过一个简单的测试用例得到的结果:
(define (first-values tree)
(cond ((null? tree) '())
((not (pair? tree)) (list tree))
(else (cons (car (first-values (car tree)))
(first-values (car (cdr tree)))))))
(define (second-values tree)
(cond ((null? tree) '())
((not (pair? tree)) (list tree))
(else (cons (cdr (second-values (car tree)))
(second-values (car (cdr tree)))))))
(define (make-tree left right)
(list left right))
(define test (make-tree
(make-tree 2 5)
(make-tree (make-tree 4 10) (make-tree 6 20))))
test
(first-values test)
(second-values test)
结果是:
((2 5) ((4 10) (6 20)))
(2 4 6 20)
((5) (10) () 20)
如您所见,第一个函数不会过滤子列表中的值,第二个函数会留下我需要使用枚举函数过滤掉的无关子列表。我真的尝试了我所能想到的每一款汽车和cdr,这是我最接近的一款。这清楚地表明,我仍然不完全理解使用列表结构,即使对于更简单的示例来说,这并不是一个问题
(作为参考,我正在使用R5R)经过一点修改,我最终得到了这个。希望有帮助
(define (first-values tree)
(cond ((null? tree) '())
((not (pair? (car tree))) (list (car tree)))
(else (append (first-values (car tree))
(first-values (cdr tree))))))
(define (second-values tree)
(cond ((null? tree) '())
((not (pair? (car tree))) (cdr tree))
(else (append (second-values (car tree))
(second-values (cdr tree))))))
使用您的测试数据:
(first-values test)
=> '(2 4 6)
(second-values test)
=> '(5 10 20)
这里有一种不同的解决方法:我们用每个返回的叶值在其父级中的位置标记它们,然后按标记进行过滤:
(define (first-values tree)
(filter-tag 0 (collect-leaf-values 0 tree)))
(define (second-values tree)
(filter-tag 1 (collect-leaf-values 0 tree)))
现在,过滤器标签
和收集叶值
功能:
(define (filter-tag tag tagged-list)
(map cdr (filter (lambda (x) (= (car x) tag)) tagged-list)))
(define (leaf? x)
(not (pair? x)))
(define (collect-leaf-values index tree)
(if (leaf? tree)
(list (cons index tree))
(append-map collect-leaf-values '(0 1) tree)))
现在已经定义了所有必要的内容。但既然您说您只是在使用普通模式,那么让我们定义过滤器
和附加映射
(注意附加映射
使用SRFI 1还提供的任何
,我们在这里也将定义一个简化版本):
我从没想过要改变基本情况!加上现在的迭代完全类似于枚举所有节点值的函数,而不是像我最后得到的那样扭曲。谢谢:)@Sophia 10次中有9次,诀窍是1)更改基本大小写和/或2)更改组合递归调用的方式;-)
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))
(define (any pred lst)
(cond ((null? lst) #f)
((pred (car lst)) => values)
(else (any pred (cdr lst)))))
(define (append-map func . lists)
(let recur ((lists lists))
(if (any null? lists)
'()
(append (apply func (map car lists)) (recur (map cdr lists))))))