我试图用从零开始并递增的数字来标记二叉树的叶子。这是我对二叉树的定义
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。 请帮忙!!
答案 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行,组装了返回对。
哇。这变得非常长。但我希望它能在某种程度上澄清一切。如果没有,请再次询问!