BST-Ocaml中的有序遍历

时间:2016-09-28 04:08:50

标签: recursion ocaml

我正在使用具有标准以下类型定义的多态二叉搜索树:

type tree =
    Empty 
  | Node of int * tree * tree (*value, left sub tree, right sub tree*);;

我想按顺序遍历这棵树并将值添加到列表中,比如说。我试过这个:

let rec in_order tree =
  match tree with 
  Empty -> []
  | Node(v,l,r) -> let empty = [] in in_order r@empty;
v::empty;
in_order l@empty
;; 

但它每次都会返回一个空列表。我不明白为什么会这样做。

2 个答案:

答案 0 :(得分:2)

当您使用递归时,您需要始终如下推理:

  • 如何解决最简单的问题?
  • 假设我有一个更简单问题的解决方案,我该如何修改它以解决更难的问题?

你已经正确地完成了第一部分,但第二部分是一团糟。

部分问题在于您没有实现您想要实施的内容。你说你想要进行遍历并将值添加到列表中。好的,那么该方法应该在某个地方列出一个列表 - 您要添加的列表。但它并没有。所以,让我们假设它确实需要这样一个参数,看看是否有帮助。这样的列表传统上称为累加器,原因很明显。

与往常一样,首先获得签名:

let rec in_order tree accumulator =

好的,什么是简单的解决方案?如果树是空的,那么将树内容添加到累加器只是标识:

match tree with
| Empty -> accumulator

现在,递归案例是什么?我们假设我们可以解决一些较小的问题。例如,我们有一个问题的解决方案"将一端的所有内容添加到累加器中,值为":

| Node (value, left, right) -> 
  let acc_with_right = in_order right accumulator in
  let acc_with_value = value :: acc_with_right in

好的,我们现在有了累加器,其中添加了一侧的所有元素。然后我们可以使用它来添加另一方的所有元素:

  in_order left acc_with_value

现在我们可以让整个事情首先实现您尝试编写的功能:

let in_order tree =
  let rec aux tree accumulator =
    match tree with
    | Empty -> accumulator
    | Node (value, left, right) -> 
      let acc_with_right = aux right accumulator in
      let acc_with_value = value :: acc_with_right in
      aux left acc_with_value in
  aux tree []     

我们已经完成了。

这一切都有意义吗?你必须(1)实际实现你说你要实现的确切事情,(2)解决基本情况,(3)假设你可以解决较小的问题并将它们组合成更大问题的解决方案。这就是您用于解决所有递归问题的模式。

答案 1 :(得分:0)

我认为你的问题归结为此。 @运算符返回一个新列表,该列表是另外两个列表的串联。它不会修改其他列表。事实上,没有任何东西可以修改OCaml中的列表。列表是不可变的。

所以,这个表达式:

r @ empty

对名为empty的值没有影响。它仍然是一个空列表。实际上,值empty也永远不会改变。 OCaml中的变量也是不可变的。

您需要设想在不修改列表或变量的情况下构造和返回值。

当你弄明白时,它不会涉及;运算符。这个操作符的作用是评估两个表达式(左侧和右侧),然后返回右侧表达式的值。它没有组合值,它执行一个动作并丢弃其结果。因此,在使用列表时它没用。 (它用于命令式构造,如打印值。)

如果您考虑使用@,而您现在正在使用;,那么您将更接近解决方案。