遍历多路树
Traverse a multiway tree
我正在尝试遍历多路树,并像 List.map 那样映射它的值。
这是我的尝试
type 'a tree = Node of 'a * ('a tree list);;
let tree_map f t =
let rec aux acc tr =
match tr with
| Node(v, []) -> Node(f v, []) :: acc
| Node(v, sub) -> let r = List.fold_left aux acc sub in Node(f v, r) :: acc
in aux [] t
;;
let t = Node (1, [Node (2, [Node (1, [])]);
Node (3, []);
Node (1, [Node (5, []);
Node (2, [])])]);;
;;
let res = tree_map (succ) t;;
我尝试了 this 答案中的建议。无法成功实施。
我的函数returns这个明显不对
val res : int tree list =
[Node (2,
[Node (2,
[Node (3, []); Node (6, []); Node (4, []); Node (3, [Node (2, [])])]);
Node (4, []); Node (3, [Node (2, [])])])]
有什么问题吗?
我看到的一个问题是您只是按原样使用 List.fold_left
的结果。但是左边的折叠将 return 一个反向列表。
# List.fold_left (fun acc n -> (n + 1) :: acc) [] [1;2;3];;
- : int list = [4; 3; 2]
第二个问题是您在同一个表达式的两个地方使用了 acc
:
let r = List.fold_left aux acc sub in Node(f v, r) :: acc
这将复制树的一部分。在我看来,其中一个地方应该使用 []
而不是 acc
。
您所指的答案是关于折叠迭代器的,即当您将某些函数应用于树的每个节点以构建一些值时。地图迭代器有点不同,更容易实现。对于每个节点,您应该 return 映射节点。
请务必记住,map
迭代器应保留数据的结构,例如,当您拥有叶节点时,您需要 return 映射的叶节点,例如,
| Node (v, []) -> Node (f v, [])
一般情况也是如此,即不使用折叠迭代器,而是需要使用map
迭代器,例如
| Node(v, sub) -> Node (f v, List.map (aux f) sub)
事实上,您甚至不需要空节点情况,因为一般情况对所有节点都适用。这将使你 tree_map
成为一个微不足道的单行者:)
并且不要忘记从 aux
中删除 acc
参数,您不需要它。
聚会有点晚了,但由于我已经完成了工作并向您展示了可以简化多少功能:
let rec tree_map f (Node (v, sub)) =
Node(f v, List.map (tree_map f) sub)
我正在尝试遍历多路树,并像 List.map 那样映射它的值。
这是我的尝试
type 'a tree = Node of 'a * ('a tree list);;
let tree_map f t =
let rec aux acc tr =
match tr with
| Node(v, []) -> Node(f v, []) :: acc
| Node(v, sub) -> let r = List.fold_left aux acc sub in Node(f v, r) :: acc
in aux [] t
;;
let t = Node (1, [Node (2, [Node (1, [])]);
Node (3, []);
Node (1, [Node (5, []);
Node (2, [])])]);;
;;
let res = tree_map (succ) t;;
我尝试了 this 答案中的建议。无法成功实施。
我的函数returns这个明显不对
val res : int tree list =
[Node (2,
[Node (2,
[Node (3, []); Node (6, []); Node (4, []); Node (3, [Node (2, [])])]);
Node (4, []); Node (3, [Node (2, [])])])]
有什么问题吗?
我看到的一个问题是您只是按原样使用 List.fold_left
的结果。但是左边的折叠将 return 一个反向列表。
# List.fold_left (fun acc n -> (n + 1) :: acc) [] [1;2;3];;
- : int list = [4; 3; 2]
第二个问题是您在同一个表达式的两个地方使用了 acc
:
let r = List.fold_left aux acc sub in Node(f v, r) :: acc
这将复制树的一部分。在我看来,其中一个地方应该使用 []
而不是 acc
。
您所指的答案是关于折叠迭代器的,即当您将某些函数应用于树的每个节点以构建一些值时。地图迭代器有点不同,更容易实现。对于每个节点,您应该 return 映射节点。
请务必记住,map
迭代器应保留数据的结构,例如,当您拥有叶节点时,您需要 return 映射的叶节点,例如,
| Node (v, []) -> Node (f v, [])
一般情况也是如此,即不使用折叠迭代器,而是需要使用map
迭代器,例如
| Node(v, sub) -> Node (f v, List.map (aux f) sub)
事实上,您甚至不需要空节点情况,因为一般情况对所有节点都适用。这将使你 tree_map
成为一个微不足道的单行者:)
并且不要忘记从 aux
中删除 acc
参数,您不需要它。
聚会有点晚了,但由于我已经完成了工作并向您展示了可以简化多少功能:
let rec tree_map f (Node (v, sub)) =
Node(f v, List.map (tree_map f) sub)