【问题标题】:Any better way to implement quicksort in ocaml?在 ocaml 中实现快速排序有什么更好的方法吗?
【发布时间】:2013-02-26 18:55:19
【问题描述】:

我在 OCaml 中实现了quicksort。代码如下:


let shuffle d =
    let nd = List.map (fun c -> (Random.bits (), c)) d in
    let sond = List.sort compare nd in
    List.map snd sond;;

let partition = function
  | [] -> ([], [], [])
  | pivot::tl ->
    let rec p (left, right) = function
      | [] -> (left, right, [pivot])
      | first::rest ->
    let c = compare pivot first
    in 
    if c > 0 then
      p (first::left, right) rest
    else 
      p (left, first::right) rest
    in
    p ([], []) tl;;

let quicksort l =
  let sl = shuffle l 
  in
  let rec qs = function
    | [] -> []
    | l ->
      let (left, right, pivot) = partition l
      in 
      (qs left) @ pivot @ (qs right)
  in 
  qs sl;;

首先,我认为也许有更好的方法来实现分区。我想到了List.partition,但我只是想自己实现关键部分

第二,我在排序中经常使用@inefficient,对吧?

有什么建议吗?


编辑

另一个需要考虑的问题是3-way quicksort 是否会影响 OCaml 中的实现?

【问题讨论】:

  • (对于它的价值,快速排序的出色之处在于它如何很好地利用了底层的可变数组表示。目前尚不清楚是否有理由将它与列表一起使用。)
  • @JeffreyScofield 哦,好的。我只是想练习我的 OCaml 技能。我认为我们应该避免使用数组,对吧?
  • @JeffreyScofield 也是,Array.length 是 O(1) 还是 O(n)?
  • Array.length 为 O(1)。
  • 你能告诉我为什么OCaml的列表使用MergeSort而不是快速排序吗?

标签: functional-programming ocaml


【解决方案1】:

p 函数缩进严重;说到缩进,我倾向于认为在下一行有一个in 的风格对于单行声明来说太过分了,所以我宁愿把它们放在单行声明的末尾。

更重要的是,它不需要将列表元组作为参数,使用两个单独的(curried)参数可以在语法上更轻松。您也可以使用标准库的List.partition 函数。

【讨论】:

    【解决方案2】:

    您可以尝试的一个微优化是执行List.concat[[qs left]; [pivot]; [qs right]] 以立即附加列表,但您需要运行一些基准测试来验证这是否有帮助。

    【讨论】:

    • 如果你想玩这个游戏,你可以让左递归调用使用reversed比较函数,这样你就可以使用List.rev_append (qs left) (pivot :: qs right)了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 2021-07-27
    • 2018-05-24
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    相关资源
    最近更新 更多