You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中为n叉树实现带中序遍历的Foldable实例

修复n叉树Foldable实例的中序遍历实现

你的代码存在明显逻辑漏洞:处理带子女节点时,既没处理当前节点x,也没处理第一个子树t,导致折叠结果缺失关键元素,自然无法通过有序性测试。

错误代码分析

原代码的第二个分支:

foldr f b (NodeL x (t:ts)) = foldr f (foldr f b ts)

这里完全忽略了t和x,仅折叠了除第一个子树外的其他子树,漏掉了当前节点和第一个子树的遍历,这是核心问题。

正确实现方案

我们沿用二叉树中序遍历的扩展逻辑:先中序遍历第一个子树,访问当前节点,再依次中序遍历剩余子树,以下是两种可行实现:

方式1:直接实现foldr

data TreeL a = NodeL a [TreeL a] deriving (Show, Eq)

instance Foldable TreeL where
  -- 叶子节点:直接将当前节点应用到折叠函数
  foldr f b (NodeL x []) = f x b
  -- 非叶子节点:按「第一个子树 → 当前节点 → 剩余子树」的顺序折叠
  foldr f b (NodeL x (t:ts)) = foldr f (f x (foldr (foldr f) b ts)) t

逻辑解释:

  • foldr (foldr f) b ts:将剩余所有子树按中序遍历折叠到初始值b,得到剩余子树的折叠结果
  • f x (...):把当前节点x插入到剩余子树折叠结果的前面(对应遍历顺序中节点在剩余子树之前)
  • foldr f (...) t:把第一个子树t的折叠结果放在最前面,符合中序遍历顺序

方式2:通过foldMap实现(更简洁直观)

利用Foldable默认foldr基于foldMap的特性,直接描述遍历顺序:

data TreeL a = NodeL a [TreeL a] deriving (Show, Eq)

instance Foldable TreeL where
  foldMap f (NodeL x ts) = case ts of
    [] -> f x
    (t:rest) -> foldMap f t <> f x <> foldMap (foldMap f) rest

这里foldMap直接定义了遍历的元素顺序:第一个子树的映射结果,拼接当前节点的映射结果,再拼接剩余子树的映射结果。对于列表[]来说,<>就是列表拼接,因此foldr (:) []会直接得到中序遍历的元素列表,完全符合你的测试需求。

验证示例

比如对于树:

testTree = NodeL 3 [NodeL 1 [], NodeL 2 []]

使用foldr (:) [] testTree会得到[1,3,2],如果测试用例的树结构保证第一个子树节点值小于当前节点、剩余子树节点值大于当前节点,就能得到有序列表。

内容的提问来源于stack exchange,提问作者Омар Ларрондо

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:40:01