将元素插入升序列表[ocaml]

时间:2013-09-11 04:05:47

标签: sorting ocaml

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

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实现上述函数,并且没有递归?

2 个答案:

答案 0 :(得分:3)

查看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。因此,您只需使用x删除List.tl

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

答案 1 :(得分:1)

我认为解决方案的方案是这样的:

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

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

此方案的简单实现将在结果中多次插入x。但在我看来,如果你使<test>足够具体,那将会奏效。

当x属于列表的开头时,此方案也不起作用。你必须单独处理这个案子。

正如加油所说,这不是建立升序清单的有效方法。 (FWIW gasche是比我更知识渊博的OCaml专家: - )