标准机器学习中的真正快速排序 [英] True QuickSort in Standard ML

查看:59
本文介绍了标准机器学习中的真正快速排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于 RosettaCode 的标准 ML 解决方案是快速排序的一个非常慢的版本,根据问题(和讨论)为什么是极简主义者,例如 Haskell 快速排序不是真正的"快速排序?",如果功能性快速排序根据 Hoare 算法?

Since RosettaCode's Standard ML solution is a very slow version of Quicksort according to the question (and discussion) "Why is the minimalist, example Haskell quicksort not a "true" quicksort?", how would a functional Quicksort look like in Standard ML if it behaved according to the complexity of Hoare's algoritm?

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) 时间转换列表无关紧要.

That is, one that employs some aspects of functional programming where it makes sense. Unlike the Haskell version that needs to encapsulate its in-place partitioning, would there be any need for a Quicksort in SML to vary in any way from the C version besides syntax? Whether the function accepts an array/vector or spends O(n) time converting the list is less relevant.

重新表述了关于约翰科尔曼评论的问题.

Rephrased question with regards to John Coleman's comments.

推荐答案

这是我的尝试:

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); 

它遵循维基百科中描述的 Hoare 算法,但使用递归而不是循环,并有一种功能性的方法来寻找要交换的索引对.毫无疑问,这远不如 2 或 3 行伪快速排序那么优雅,它通常在函数式编程的介绍性处理中教授,并且它并没有真正展示函数式编程的力量.希望比我更了解 SML 的人能想出更惯用的 SML qsort.

It follows Hoare's algorithm as described in Wikipedia fairly closely but uses recursion rather than loops, and has a somewhat functional approach for looking for pairs of indices to swap. There is no question that this is nowhere nearly as elegant as the 2 or 3 line pseudo-quicksort which is often taught in introductory treatments of functional programming and it doesn't really showcase the powers of functional programming. Hopefully someone who knows more SML than I can come up with a more idiomatic SML qsort.

这篇关于标准机器学习中的真正快速排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆