【问题标题】:True QuickSort in Standard ML标准 ML 中的真正快速排序
【发布时间】:2017-06-25 08:36:08
【问题描述】:

由于根据问题(和讨论)“Why is the minimalist, example Haskell quicksort not a "true" quicksort?”,RosettaCode's Standard ML solution 是 Quicksort 的一个非常慢的版本,如果按照 Hoare's algoritm 的复杂性表现,功能性 Quicksort 在标准 ML 中会是什么样子?

fun quicksort [] = []
  | quicksort (x::xs) =
    let 
        val (left, right) = List.partition (fn y => y<x) xs
    in
        quicksort left @ [x] @ quicksort right
    end

也就是说,它在有意义的地方使用了函数式编程的某些方面。与 需要 封装其就地分区的 Haskell 版本不同,除了语法之外,SML 中的快速排序是否需要与 C 版本有任何不同?函数是否接受数组/向量或花费 O(n) 时间转换列表的相关性较低。

编辑:改写了关于 John Coleman 的 cmets 的问题。

【问题讨论】:

  • 由于 SML 的不纯部分涉及ref、可变数组、循环等,因此编写命令式就地快速排序当然有些容易。有趣的问题是,您是否可以在 SML 中编写一个既高效又(大部分)功能的快速排序。

标签: quicksort sml


【解决方案1】:

这是我的尝试:

fun swap(A,i,j) = 
    let
        val t = Array.sub(A,i)
    in
        Array.update(A,i,Array.sub(A,j));
        Array.update(A,j,t)
    end

fun firstAfter(A,i,f) =
    if f(Array.sub(A,i)) then i else firstAfter(A,i+1,f)

fun lastBefore(A,j,f) =
    if f(Array.sub(A,j)) then j else lastBefore(A,j-1,f)

fun partition(A,lo,hi)=
    let 
        fun partition'(A,lo,hi,pivot) = 
            let 
                val i = firstAfter(A,lo,fn k => k >= pivot)
                val j = lastBefore(A,hi,fn k => k <= pivot)
            in
                if i >= j then 
                    j
                else
                (
                    swap(A,i,j);
                    partition'(A,i+1,j-1,pivot)
                 )
             end
   in
      partition'(A,lo,hi,Array.sub(A,lo))
   end

fun quicksort(A,lo,hi) = 
    if hi <= lo then
        ()
    else
        let
            val p = partition(A,lo,hi)
        in
            (
                quicksort(A,lo,p);
                quicksort(A,p+1,hi)
             )
        end;

fun qsort A = quicksort(A,0,Array.length A - 1); 

它遵循 Wikipedia 中描述的 Hoare's algorithm 相当接近,但使用递归而不是循环,并且具有查找要交换的索引对的某种功能性方法。毫无疑问,这远没有 2 或 3 行伪快速排序那么优雅,后者经常在函数式编程的介绍性处理中被教授,并且它并没有真正展示函数式编程的力量。希望比我了解更多 SML 的人能想出一个更惯用的 SML qsort。

【讨论】:

    【解决方案2】:

    您可以在我的 github 存储库 https://github.com/Khanzadeh-AH/sorting_algorithms_SML 中找到一些用标准 ML 编写的排序算法

    fun pivot_split([], pivot) = ([],[])
    |   pivot_split(h::t, pivot) =
    
            let
                val (L,R) = pivot_split(t, pivot)
            in
    
                if h < pivot then (h::L, R)
                else (L, h::R)
            end;
        
        
    
    fun quicksort([]) = []
    |   quicksort([a]) = [a]
    |   quicksort(h::t) =
            let
                val (L, R) = pivot_split(t, h)
            in
                quicksort(L)@[h]@quicksort(R)
            end;
    
    
    
    pivot_split([12,3,5,67,1,2,3,5,7],3);
    
    quicksort([12,3,5,67,1,2,3,5,7]);
    

    【讨论】:

    • 啊,@Khanzadeh_AH。您提供的“快速排序”并不是真正的快速排序。如果你不知道为什么,你可以阅读文章Forward Is Not Enough。如果推理不够清楚,请随时提出问题。
    猜你喜欢
    • 2014-10-10
    • 1970-01-01
    • 2016-06-11
    • 2011-05-05
    • 1970-01-01
    • 2021-07-27
    • 2012-03-22
    • 2013-04-18
    • 2023-02-02
    相关资源
    最近更新 更多