Haskell中如何同时向下与横向构建指定结构的树形结构?
解决Haskell中构建带横向分支与向下递归的树形结构问题
首先,我得先拆解你要的树形结构的规律:这本质上是所有以1开头的[1,2,3,4]排列的前缀树——每个节点代表排列的一个前缀,子节点是所有还没出现在当前前缀里的元素,递归下去直到前缀包含所有元素(此时没有子节点)。
你的down函数只能生成单链,side函数不仅有语法错误(map作用在Int类型的y上了),也没有处理递归向下生长的逻辑。下面是整合了横向分支和向下递归的完整解决方案:
方案1:用列表过滤实现(无需额外导入)
先复用你定义的Tree类型:
data Tree a = Node a [Tree a] deriving (Show)
然后实现构建树的核心函数:
buildTree :: Int -> [Int] -> [Int] -> Tree Int buildTree current used all = Node current children where -- 找出当前可用的子节点:所有未在当前路径中使用过的元素 available = filter (`notElem` used) all -- 对每个可用元素,递归构建它的子树(把当前元素加入已使用集合) children = map (\x -> buildTree x (x : used) all) available
初始调用
你的需求是根节点为1,所有元素是[1,2,3,4](根+给定的列表[2,3,4]),所以调用:
targetTree = buildTree 1 [1] [1,2,3,4]
打印这个targetTree,会得到和你给出的完全一致的结构:
Node 1 [Node 2 [Node 3 [Node 4 []],Node 4[Node 3 []]], Node 3 [Node 2 [Node 4 []], Node 4 [Node 2 []]], Node 4 [Node 2 [Node 3 []], Node 3 [Node 2 []]]]
方案2:用Set实现(更高效,适合大集合)
如果元素数量较多,用Data.Set处理可用元素会更高效,避免重复检查:
import qualified Data.Set as Set data Tree a = Node a [Tree a] deriving (Show) buildTreeSet :: Int -> Set.Set Int -> Set.Set Int -> Tree Int buildTreeSet current used all = Node current children where available = Set.difference all used children = map (\x -> buildTreeSet x (Set.insert x used) all) (Set.toList available)
初始调用
targetTreeSet = buildTreeSet 1 (Set.singleton 1) (Set.fromList [1,2,3,4])
这个版本的输出和列表版本完全一致,但对于元素较多的场景性能更好。
为什么你的之前尝试没成功?
down函数:每次只取列表的第一个元素生成子节点,只能构建单链,无法生成横向的多分支;side函数:存在语法错误(map (\x -> Node x []) y中y是Int,不是列表),而且只生成了一层子节点,没有递归向下构建更深的层级。
把横向分支(遍历所有可用元素生成子节点)和向下递归(每个子节点继续生成自己的子树)结合起来,就得到了你需要的树形结构。
内容的提问来源于stack exchange,提问作者llamaro25
相关产品推荐
相关产品推荐

