【问题标题】:OCaml option value treeOCaml 选项值树
【发布时间】:2012-09-21 20:21:11
【问题描述】:

我的任务是编写一个 ‘a btree -> ‘a option list 类型的函数,它将给定的树存储在 ‘a option 类型的元素列表中,按后缀顺序(后序)。

内部节点将由None 表示,值为x 的外部节点(叶子)将由Some x 表示。

到目前为止,叶子的操作很容易,但是如何将其放入'a option list

type 'a btree = L of 'a | N of 'a btree * 'a btree ;;

let rec store t =
    match t with
        | L x -> Some x
        | N (a,b) -> None ???   
;;

我知道的第二个匹配案例不正确,但是如何解决呢?

【问题讨论】:

  • 对了,这是作业吗?如果是的话也不是坏事,但这样说也算是礼貌。
  • 是的,希望是最后一个 :D。很高兴我对 Ocaml 有一些概念,但老实说,我将来永远不会使用它。
  • 您可能会感到惊讶;我在工作中多次使用它,这不是你所说的学术环境。有时它只是适合这项工作的工具。
  • 我建议您查看@gasche 的答案;使用累加器会使这个大大更快,并避免列表追加,每个列表的长度为 O(n)。
  • 嗯?那将是前序遍历,而不是后序遍历。作为参考,我使用来自the Wikipedia page on tree traversal 的定义。此外,您的更改也无济于事,因为它允许您从一片叶子开始;这只是定义的函数的性质。您可以尝试进一步限制它,不允许您从一片叶子开始,但这会不必要地难看。

标签: tree ocaml


【解决方案1】:

如果您查看您的第一个案例,您会发现它也不完全存在;它正在返回 'a option,但您希望该函数返回 'a option list

很明显你会返回一个列表,所以先解决这个问题:

let rec store = function
  | L x -> [Some x]
  | N (a,b) -> [None] (* ??? *)

现在让我们解决第二种情况;我们想将None 附加到我们的输出中,但在此之前,我们需要子树的节点:

let rec store = function
  | L x -> [Some x]
  | N (a,b) -> (store a) @ (store b) @ [None]

@ 有类型

'a list -> 'a list -> 'a list

即它将列表连接在一起。我们想加入左子树的结果列表,然后是右子树,最后是这个内部节点的结果。

【讨论】:

    【解决方案2】:

    如果有人对这种改进感兴趣,可以通过线程化一个额外的累加器参数,在性能方面比 Len 的解决方案做得更好。

    这个想法是从一个函数store : 'a btree -> 'a option list 转移到一个函数store' : 'a btree -> 'a option list -> 'a option list,它接受一个树并产生一个列表,函数store' : 'a btree -> 'a option list -> 'a option list 将树的元素添加到作为参数传递的现有列表中.

    let rec store' t acc = match t with
      | L x -> Some x :: acc
      | N (a, b) ->
        store' a (store' b (None :: acc))
    

    使用此定义,元素仅在最终结果列表中添加一次,而不是先用于构建临时store a 列表,然后通过(@) 运算符将第二次附加到最终结果中。

    参数顺序很重要,因为在acc 之前写入t 可以直观地了解列表中的最终元素顺序:t 的元素将是中已经存在的元素acc。这使得 N 的大小写可以非常自然地阅读:很容易看出结果将首先包含 a 的元素,然后是 b,然后是 None,然后是 acc

    最后,你当然可以用store'来定义store

    let store t = store' t []
    

    习惯上将第一个定义包装在第二个定义中(如果您不想将这个“低级”函数暴露给用户),并给它与外部定义相同的名称(这不会'不冲突,因为它不是递归的,所以不进入内部作用域):

    let store t =
      let rec store t acc = match t with
        | L x -> Some x :: acc
        | N (a, b) ->
          store a (store b (None :: acc))
      in store t []
    

    当然,这个定义是否比 Len 的定义“更好”取决于你的评价标准是什么。 Len 的解决方案更短、更易于阅读,并且更紧密地映射了原始问题。

    (您可以通过使用惰性枚举而不是严格列表来获得两全其美,但那是另一回事了。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      相关资源
      最近更新 更多