Sml折叠一棵树 [英] Sml folding a tree
问题描述
我试图通过使用折叠函数来获得树的产品,到目前为止,这就是我所拥有的。我很困惑如何在遍历树的时候使用fold方法
数据类型'a bin_tree ='a
| 'a bin_tree *'的节点a bin_tree
好玩的treefold g z空白= z
| treefold gz(Node(l,x,r))= g(x,g(treefold gzl,treefold gzr)
在折叠二叉树时,
datatype'a tree = Leaf |'a tree *'a *'a tree
的分支您可以在避免堆栈溢出s。
fun treecata_preorder f acc1 Leaf = acc1
| treecata_preorder f acc1(branch as branch(left,a,right))=
let val acc2 = treecata_preorder f acc1 left
val acc3 = f(a,branch,acc2)
val acc4 = treecata_preorder f acc3 right acc $ 4中的
结尾
这是 treefold_preorder
,其中 f
被送到整个分支
。
这可以让你例如找到一个祖先树中的一个谓词持有它们的子树,
fun treefilter pred =
treecata_preorder(fn (x,xtree,acc)=> if pred xtree then x :: acc else acc)[]
fun branchValue Leaf = NONE
| branchValue(Branch(_,value,_))=某个值
有趣的父母叶= []
|父类(Branch(left,_,right))=
List.mapPartial(fn xopt => xopt)[branchValue left,branchValue right]
type name = string
类型age = int
datatype person =名字的年龄*年龄
有趣的退休(Person(_,age))= age> = 70
fun hasRetiredParent tree = List。存在退休(父母树)
val personsWith RetiredParents = treefilter hasRetiredParent
树遍历的另一个概念拉链(LYAH章节)。
I am trying to get the product of a tree by using the fold function so far this is what I have. I am confused on how to use the fold method while transversing the tree
datatype 'a bin_tree = Leaf of 'a
| Node of 'a bin_tree * 'a bin_tree
fun treefold g z Empty = z
| treefold g z (Node (l, x, r)) = g(x, g(treefold g z l, treefold g z r)
When folding a binary tree,
datatype 'a tree = Leaf | Branch of 'a tree * 'a * 'a tree
you may traverse it in different ways. Among common strategies you have,
(* Pre-order *)
fun treefold_preorder f acc1 Leaf = acc1
| treefold_preorder f acc1 (Branch (left, a, right)) =
let val acc2 = treefold_preorder f acc1 left
val acc3 = f (a, acc2)
val acc4 = treefold_preorder f acc3 right
in acc4 end
(* In-order *)
and treefold_inorder f acc1 Leaf = acc1
| treefold_inorder f acc1 (Branch (left, a, right)) =
let val acc2 = f (a, acc1)
val acc3 = treefold_inorder f acc2 left
val acc4 = treefold_inorder f acc3 right
in acc4 end
(* Post-order *)
and treefold_postorder f acc1 Leaf = acc1
| treefold_postorder f acc1 (Branch (left, a, right)) =
let val acc2 = treefold_postorder f acc1 left
val acc3 = treefold_postorder f acc2 right
val acc4 = f (a, acc3)
in acc4 end
which Wikipedia nicely illustrates as,
Usage
val treelist = treefold op:: []
val treeproduct = treefold op* 1
val treecount = treefold (fn (_, count) => count + 1) 0
Extra
In-order traversal isn't meaningful if each branch/node doesn't have an 'a value.
See also how to apply tail-recursion on trees to avoid stack overflows.
For some problems that involve tree traversal, it may be useful to supply the context of the traversal like paramorphisms do:
fun treecata_preorder f acc1 Leaf = acc1
| treecata_preorder f acc1 (branch as Branch (left, a, right)) =
let val acc2 = treecata_preorder f acc1 left
val acc3 = f (a, branch, acc2)
val acc4 = treecata_preorder f acc3 right
in acc4 end
This is a slight generalisation of treefold_preorder
in which f
is fed the entire branch
.
This lets you e.g. find people in an ancestry tree for which a predicate holds for their subtree,
fun treefilter pred =
treecata_preorder (fn (x, xtree, acc) => if pred xtree then x::acc else acc) []
fun branchValue Leaf = NONE
| branchValue (Branch (_, value, _)) = SOME value
fun parents Leaf = []
| parents (Branch (left, _, right)) =
List.mapPartial (fn xopt => xopt) [branchValue left, branchValue right]
type name = string
type age = int
datatype person = Person of name * age
fun retired (Person (_, age)) = age >= 70
fun hasRetiredParent tree = List.exists retired (parents tree)
val personsWithRetiredParents = treefilter hasRetiredParent
Another neat notion for tree traversal are zippers (LYAH chapter).
这篇关于Sml折叠一棵树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!