algorithm - 层次二叉树遍历的魔法代码——发生了什么?

标签 algorithm tree functional-programming ocaml

我们有一个二叉树的定义:

type 'a tree =
  | Node of 'a tree * 'a * 'a tree
  | Null;;

还有一个很有用的遍历树的函数"

let rec fold_tree f a t =
  match t with
  | Null -> a
  | Node (l, x, r) -> f x (fold_tree f a l) (fold_tree f a r);;

这是一个“魔法”函数,当给定一棵二叉树时,它返回一个列表,其中我们有特定级别的元素列表,例如,当给定一棵树时:

tree
(来源:ernet.in)

函数返回 [[1];[2;3];[4;5;6;7];[8;9]]。

let levels tree =
  let aux x fl fp = 
    fun l ->
    match l with
    | [] -> [x] :: (fl (fp []))
    | h :: t -> (x :: h) :: (fl (fp t))
  in fold_tree aux (fun x -> x) tree [];;

显然它有效,但我无法全神贯注。谁能用简单的术语解释发生了什么?为什么这个功能有效?

最佳答案

如何合并两个子树的两个层列表并获得错误树的层列表?假设你有这棵树

   a
  / \
 x   y

其中 xy 是任意树,它们的层列表为 [[x00,x01,...],[x10,x11 ,...],...][[y00,y01,...],[y10,y11,...],...]

新树的层列表将是[[a],[x00,x01,...]++[y00,y01,...],[x10,x11,...]++[y10,y11,...],...]。这个函数是怎么构建的?

让我们看看这个定义

let rec fold_tree f a t = ...

并查看我们在 levels 的定义中传递给 fold_tree 的参数类型。

... in fold_tree aux (fun x -> x) tree []

所以第一个参数 aux 是某种长而复杂的函数。我们稍后会返回。

第二个参数也是一个函数——恒等函数。这意味着 fold_tree 也将返回一个函数,因为 fold_tree 总是返回与其第二个参数相同类型的值。我们将讨论应用于这组参数的函数 fold_tree 获取一个层列表,并将给定树的层添加到其中。

第三个参数是我们的树。

等等,第四个参数是什么? fold_tree 只应该得到树?是的,但由于它返回一个函数(见上文),该函数将应用于第四个参数,即空列表。

让我们回到aux。此 aux 函数接受三个参数。一个是树的元素,另外两个是子树折叠的结果,即 fold_tree 返回的任何内容。在我们的例子中,这两件事又是函数。

所以 aux 得到一个树元素和两个函数,并返回另一个函数。那是哪个函数?它需要一个层列表,并向其中添加给定树的层。它是怎么做到的?它将树的根添加到列表的第一个元素(顶层),然后通过调用将右子树的层添加到列表的尾部(顶层以下的所有层) right 函数,然后通过调用 left 函数 将左子树的层添加到结果中。或者,如果传入列表为空,则通过将上述步骤应用于空列表,它只是重新列出图层。

关于algorithm - 层次二叉树遍历的魔法代码——发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26950438/

相关文章:

reference - 如何使用 Rust 对树结构中的单个节点进行多个引用

ruby - 如何在 Ruby 中编写条件 lambda?

functional-programming - 替换符号表达式中的符号

排除数字的算法

javascript - 如何计算javascript中的日出和日落?

javascript - 在javascript中将文件/目录结构转换为 'tree'

java - 在 Java 中折叠顺序流

找到最佳 x y 索引的算法,使每个象限中的点数总和最小化

c# - 使用多线程暴力破解密码

mysql - 创建文件夹/文件结构