生成具有n个节点的所有二叉树OCaml

生成具有n个节点的所有二叉树OCaml,ocaml,Ocaml,我正在尝试编写一个代码,生成具有n节点的所有二叉树(因此程序必须返回一个列表,我们可以在其中找到具有n节点的所有不同二叉树) 以下是我表示二叉树的方式: type 'a tree = Empty | Node of 'a * 'a tree * 'a tree 因此,我试图实现一个函数all_tree:int->tree list,以便: 所有树0=[空] all_tree 1=[节点('x',空,空)] all_tree 2=[Node('x',Node('x',Empty,Empty),E

我正在尝试编写一个代码,生成具有
n
节点的所有二叉树(因此程序必须返回一个列表,我们可以在其中找到具有
n
节点的所有不同二叉树)

以下是我表示二叉树的方式:

type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
因此,我试图实现一个函数
all_tree:int->tree list
,以便:

  • 所有树0=[空]
  • all_tree 1=[节点('x',空,空)]
  • all_tree 2=[Node('x',Node('x',Empty,Empty),Empty);Node('x',Empty,Node('x',Empty,Empty))]
  • 我尝试了好几个主意,但没有成功。例如,我们可以尝试以下方法:

    let rec all_tree result = function
       |0 -> r
       |s -> all_tree ((List.map (fun i -> Node('x',i,Empty)) result)@(List.map (fun i -> Node('x',Empty,i)) result) ) (s-1)
    in all_tree [Empty] (*some number*)
    

    这段代码不起作用,因为它没有生成所有的可能性。

    这里有一个可能的答案

    让rec all_trees=函数
    |0->[空]
    |n->
    让result=ref[]输入
    对于i=0到n-1 do
    让左侧=所有树i
    右侧=中的所有树(n-1-i)
    List.iter
    (有趣的左树->
    List.iter
    (有趣的右树->
    结果:=(节点('x',左树,右树))::(!结果)
    )
    右侧
    )
    左侧
    完成;
    !结果
    ;;
    
    这非常简单:一个n>0个节点的树是一个顶部有1个节点的树,然后下面的n-1个节点在左边的某个数字和右边的某个数字之间分开。因此,我们循环i从0到n-1,通过左侧所有可能的数值,n-i-1将是右侧的节点数。我们递归地调用
    所有_树
    以获得具有i和n-i-1节点的树,并简单地将它们聚合

    请注意,这是一个非常糟糕的实现。它拥有递归函数应该避免的一切。看看如何改进它(首先要做的事情之一是缓存结果,而不是多次重新计算相同的内容)



    我确实同意问题的意见,尽管在这种项目中,编写打印机将是第一步,因为阅读像
    [Node('x',Node('x',Empty,Node('x',Node('x',Empty,Empty)),Empty这样的杂乱无章的东西真的很烦人。)
    。更好地命名变量也会使人们更容易阅读您的代码,并增加有人帮助您的机会。通常,当人们就如何正确提问向您提出建议时,倾听他们的意见会使您更容易在现在和将来的问题中获得答案。例如,在我自己的代码中,我使用了
    I
    作为循环索引。在我编写代码时,这对我来说是有意义的,但是当你阅读代码时,也许你更喜欢阅读类似
    left_side_nodes
    或类似的内容,这会使这个变量的作用变得显而易见。在你自己的场景中也是一样的:你uld调用
    i
    类似于
    子树
    或者更明确的东西。事实上,正确命名它可以让你意识到你的代码有什么问题。通常,如果你不能正确命名一个变量,那就是你并不真正理解它在做什么(甚至是局部变量).

    你怎么知道它不会产生所有的可能性?因为例如,我从未得到二叉树节点('x',Node('x',Empty,Empty),Node('x',Empty,Empty)),你是如何得出这种可能性的,为什么你认为你的代码找不到它的。请具体说明。“不起作用”这不是一个非常有用的问题描述。您可能需要阅读并尝试相应地编辑您的问题。我只是想要解决问题的想法或完整的解决方案。正如我在上面发布的链接所解释的那样,这并不是真正的目的。即使您在其他地方进行了解释,您也应该正确地格式化代码和命名变量,因为如果你这样做的话,你就不必费劲去理解你的代码了。如果你不愿意费心去帮助我们帮助你,我们为什么要费心去帮助你呢?