Tree 在Scheme中的二叉树的所有节点上筛选相同索引?

Tree 在Scheme中的二叉树的所有节点上筛选相同索引?,tree,scheme,lisp,binary-tree,sicp,Tree,Scheme,Lisp,Binary Tree,Sicp,这开始是对SICP中练习2.29的误解,后来成为了个人的好奇心。这似乎很简单,我感到很尴尬,因为我很难找到一个适用于所有情况的解决方案。显然,我知道如何计算树上的节点数,以及如何将每个节点中的值枚举到一个列表中,但这两种算法都不能帮助我筛选每个节点中的相同索引 给定任何表示为嵌套列表的二叉树,其中每个节点持有一个或两个整数,应该有一个函数在每个节点中返回第一个值的列表,还有一个函数在每个节点中返回第二个值(请记住,并非所有节点都有第二个值) 以下是我到目前为止通过一个简单的测试用例得到的结果:

这开始是对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))))))