我正在使用具有标准以下类型定义的多态二叉搜索树:
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
;;
但它每次都会返回一个空列表。我不明白为什么会这样做。
答案 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中的变量也是不可变的。
您需要设想在不修改列表或变量的情况下构造和返回值。
当你弄明白时,它不会涉及;
运算符。这个操作符的作用是评估两个表达式(左侧和右侧),然后返回右侧表达式的值。它没有组合值,它执行一个动作并丢弃其结果。因此,在使用列表时它没用。 (它用于命令式构造,如打印值。)
如果您考虑使用@
,而您现在正在使用;
,那么您将更接近解决方案。