标记二叉树的叶子

时间:2013-08-12 11:40:13

标签: tree functional-programming ocaml

我试图用从零开始并递增的数字来标记二叉树的叶子。这是我对二叉树的定义

  type btree = I of int | Node of string * btree * btree

应用我的函数时,应该从最左边的叶子开始用数字标记树叶,标记为零。对于前节点(“a”,节点(“b”,I 25,I 54),节点(“c”,I 12,I 47))应返回树节点(“a”,节点(“b”,I 0) ,I 1),Node(“c”,I 2,I 3))。我怎样才能做到这一点? 我试着写代码,但没有给出合适的结果。这是我的代码:

 let mark bst =
  let number x = function
  |Node(a, I b, I c) -> Node(a, I x, I (x + 1))
  |Node(a, b, I c) -> Node(a, (number x b), I(x + 1))
  |Node(a, I b, c) -> Node(a, x, (number (x + 1) c)
  |Node(a, b, c) -> Node(a, (number x b), (number x c))
 in number 0 bst

此代码编译正常,但是从开头分别对左和右子树进行编号,即0。 请帮忙!!

1 个答案:

答案 0 :(得分:3)

以下内容应该有效。它一个接一个地处理子树。

let mark bst = 
  let rec number = function
    | (x, I a) -> (x+1, I x)
    | (x, Node(a, b, c)) -> 
    let p1 = number (x,b) in
    let p2 = number ((fst p1),c) in
    ((fst p2),Node(a,(snd p1), (snd p2)))
  in snd (number (0,bst))

以下是我在您的示例中运行时获得的内容。老实说,这是我尝试过的唯一例子。

# let tr =  Node("a", Node("b", I 25, I 54), Node("c", I 12, I 47));;
val tr : btree = Node ("a", Node ("b", I 25, I 54), Node ("c", I 12, I 47))
# markit tr;;
- : btree = Node ("a", Node ("b", I 0, I 1), Node ("c", I 2, I 3))

代码说明: 要按从左到右的升序唯一地标记每个叶子,您必须查看每个子树,一次一个。在查看左子树之后,您需要知道您在标记过程中走了多远,即下一个标签是什么。要获得此功能,我的函数number会返回一对类型int * btree,而您的函数会返回btree。该对中的int是下一个未使用的标签。返回一对,允许我们有两个返回值。聪明!

我想你理解前两行,因为它们与你的相同(差不多 - 记得在定义递归函数时使用let rec)。在函数mark中,number函数在最后一行启动 - 就像在代码中一样。不同之处在于,我不是像给你那样给函数输入两个输入值,而是给它一个;一对价值观。但最后,我们想要的只是该对中的第二个条目,我们使用snd提取。在第3-4行中,我们检查是否正在查看整数或节点(即叶子或子树)。请注意,根据您的类型定义,这两种情况是唯一的可能性。如果我们正在查看节点,我们将需要首先遍历左子树,这发生在第5行。在遍历righ子树之后,我们仍然需要将下一个未使用的标签传递给父节点,这就是我们需要的原因在第7行,组装了返回对。

哇。这变得非常长。但我希望它能在某种程度上澄清一切。如果没有,请再次询问!