【问题标题】:inserting element into list of ascending order [ocaml]将元素插入升序列表 [ocaml]
【发布时间】:2013-09-11 04:05:46
【问题描述】:

以下代码将一个元素插入到按升序排序的列表中。

let rec insert x l =
  match l with
    | [] -> [x]
    | y::ys -> if x < y then x::y::ys else y::insert x ys

但是,我如何只使用 List.fold_right 实现上述功能,而没有递归呢?

【问题讨论】:

  • fold_right 是递归
  • 我的意思是我希望代码看起来像...'let insert x l = ...' 而不是'let rec insert x l = ...'
  • 我不明白您为什么要使用折叠进行插入。 fold 必须扫描所有列表元素,但 insert 不需要。如果是家庭作业,那就不是好作业,可能会让你感到困惑。

标签: sorting ocaml


【解决方案1】:

List.fold_right的最简单实现:

let rec fold_right f li init = match li with
  | [] -> init
  | y::ys -> f y (fold_right f ys init)

你可以试试

let insert x li =
  let add_x y inserted_ys =
    if x < y then x::y::inserted_ys
    else y::inserted_ys
  in
  List.fold_right add_x li [x]

问题在于then 分支不正确:您将在两个位置获得x,分别位于列表的开头和inserted_ys。但是,您知道x 将在inserted_ys 列表中的哪个位置:就在开头,因为ys 的所有元素都大于x。所以你可以用List.tl删除x

let insert x li =
  let add_x y inserted_ys =
    if x < y then x::y::(List.tl inserted_ys)
    else y::inserted_ys
  in
  List.fold_right add_x li [x]

注意这是写insert 的复杂方式。更好的技术是让add_x 返回一对列表和一个布尔值,布尔值告诉您x 是否已经被添加。

【讨论】:

  • 感谢您的建议!
【解决方案2】:

我想解决方案的方案是这样的:

fun insert x l =
    List.fold_right (fun a b -> if <test> then a :: x :: b else a :: b) l []

每次调用该函数时,它都会看到最终列表的末尾,以及通常会在列表前面的下一个新元素。似乎可以根据这些信息决定是否在当前位置插入您的值x

这种方案的简单实现会在结果中多次插入 x。但在我看来,如果您将 &lt;test&gt; 足够具体,它将起作用。

当 x 位于列表的开头时,此方案也不起作用。您必须单独处理这种情况。

正如加什所说,这不是建立升序列表的有效方法。 (FWIW gasche 是一位比我知识渊博的 OCaml 专家 :-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    相关资源
    最近更新 更多