是否有可能在haskell中实施一般的就地快速排序?

时间:2013-02-03 18:19:44

标签: haskell quicksort

术语一般(违背专门)中的问题表示该功能可以,只要它们是一种类型,是一个实例{{的项目进行排序1}}。

考虑一个最着名的haskell广告

Ord

上述实施不到位 我试图写一个就地版本。 就地快速进行快速排序很容易。通常,我们只需要一个可变数组,然后选择quicksort :: Ord a => [a] -> [a] quicksort [] = [] quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater) where lesser = filter (< p) xs greater = filter (>= p) xs 我的实现是就地并且运行得很好,但我对它的类型签名不满意

Foreign.Marshal.Array

更确切地说,类型约束(Ord a, Storable a) => [a] -> IO [a] 让我烦恼。

显然,如果我们要对项目进行排序,则需要Storable a约束,而Ord则不需要。{ 相比之下,经典快速排序或Storablesort的类型签名为Data.List。约束只是Ord a => [a] -> [a]

我没有找到摆脱额外约束的方法。

我搜索了Stackoverflow,发现了一些关于haskell的就地快速排序的问题,例如
How do you do an in-place quicksort in Haskell
Why is the minimalist, example Haskell quicksort not a "true" quicksort?

不幸的是,他们主要担心的是就地。这里给出的所有现场快速排序示例都有其他类型限制 例如,iqsort given by klapaucius具有类型签名

Ord

有谁知道如何使用类型签名iqsort :: (Vector v a, Ord a) => v a -> v a 实现就地快速排序haskell功能?
我知道如何制作就地快速排序,但我不知道如何制作 general

2 个答案:

答案 0 :(得分:5)

iqsort实际上对我来说非常普遍。如果您查看Data.Vector.Generic haddocks,实际上您可以将该接口用于任何 a!区别在于给定的函数是 more 泛型,因为它允许您选择未装箱的向量,当然这只适用于某些 a

以下是链接:http://hackage.haskell.org/packages/archive/vector/0.10.0.1/doc/html/Data-Vector-Generic.html

因此,如果选择要装箱的V,矢量约束就会消失。

答案 1 :(得分:3)

是的,这是可能的。 (尽管在Haskell中,只有在真正需要最佳性能的情况下才能使用这种命令式算法。)

我知道2种这样的算法:

    来自 vector-algorithms
  • sort
  • 来自qsort
  • marray-sort(或内省),我还没有发布到Hackage。 (如果您需要,请告诉我。)它适用于mutable arrays

Introsort基本上是精简快速排序,具有 O(n log n)最坏情况的复杂性。)

我不确定MVector,但对于MArray,您不必担心其他约束MArray a e m。他们在那里使类型更通用,而不是更少。像

这样的签名
qsort :: (MArray a e m, Ord e) => a Int e -> m ()

允许对不同的数组表示使用相同的算法。对于某些数据类型,您可以拥有该类型的专用数组,这些数组比通用数组更快,更紧凑。例如,如果要对8位整数进行排序,则unboxed arrays有一个专门的实例MArray IOUArray Int8 IO。对于仅使用多态的这种数组,qsort的特化是

qsort :: IOUArray Int Int8 -> IO ()

但您也有实例MArray IOArray e IO的实例e。通过qsort使用IOArray,您可以获得e无约束的专业化:

qsort :: (Ord e) => IOArray Int e -> IO ()

此外,如果您使用STArrayST monad,则可以使用相同的函数对数组进行就地排序,稍后将结果作为纯值获取,而不使用{{1 }}