Scheme获取父节点子节点函数异常及子列表首元素Cons问题
问题分析与修复方案
咱们先聊聊你现有代码的核心问题:你的children函数只在树的顶层元素里找目标节点,完全没递归进嵌套的子列表里。比如你要找2的时候,它其实藏在(2 (4 ...) (12 ...) (16))这个子列表的第一个位置,但你的函数只会检查顶层的10、(2 ...)、(5 ...)、(6)这些元素——而(= 2 (2 ...))这种数字和列表的比较,要么直接报错,要么返回不符合预期的结果,自然找不到目标节点。
另外你的getchilds思路其实是对的,但它处理的输入不对:它应该接收目标节点的子节点列表(也就是(cdr 目标节点)),而不是当前树的cdr(只有顶层节点的情况才凑巧对)。
修正后的代码
我重新写了两个函数,解决了嵌套查找的问题,也完美实现了你要的“把每个子列表的第一个元素cons起来”的需求:
1. children:递归遍历所有节点找目标
这个函数会钻到树的每一层,不管节点嵌套多深,只要找到目标值对应的节点,就去提取它的子节点头部;没找到就继续递归找。
(define (children elem tree) (cond ((null? tree) '()) ; 空树直接返回空 ((pair? (car tree)) ; 当前元素是一个节点(列表形式) (if (= elem (caar tree)) ; 看看这个节点的第一个元素是不是目标值? (get-child-heads (cdar tree)) ; 是!那提取它的子节点头部 (append (children elem (car tree)) ; 不是,先递归找这个节点的子节点 (children elem (cdr tree))))) ; 同时也不能忘了找兄弟节点 (else (children elem (cdr tree))))) ; 当前元素是原子,跳过,继续找兄弟节点
2. get-child-heads:收集子节点的第一个元素
这就是你要的逻辑:遍历子节点列表,把每个子节点的第一个元素(也就是子节点的值)用cons串起来:
(define (get-child-heads child-nodes) (cond ((null? child-nodes) '()) ((pair? (car child-nodes)) ; 确认当前子节点是有效的列表形式 (cons (caar child-nodes) (get-child-heads (cdr child-nodes)))) (else (get-child-heads (cdr child-nodes))))) ; 如果遇到非列表元素,直接跳过
测试一下效果
找顶层节点
10:(children 10 '(10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6))) ; 输出: (2 5 6) 和你预期的一样找嵌套节点
2:(children 2 '(10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6))) ; 输出: (4 12 16) 这就是你想要的正确结果啦再试试更深的节点
9:(children 9 '(10 (2 (4 (9 (3)) (12 (1 (2))) (16))) (5 (7) (21)) (6))) ; 输出: (3) 完全没问题
为啥这么改?
- 递归查找全覆盖:原来的函数只扫顶层,现在
children会钻进每个子节点内部,不管节点藏在哪一层都能找到。 - 精准提取子节点头部:
get-child-heads专门处理目标节点的子节点列表,逐个把每个子节点的第一个元素cons起来,完全实现了你要的功能。
内容的提问来源于stack exchange,提问作者cicero866
相关产品推荐
相关产品推荐

