【发布时间】:2013-01-05 06:05:13
【问题描述】:
haskell 库中是否有任何函数可以在 O(n) 时间内对整数进行排序? [通过,O(n) 我的意思是比比较排序更快并且特定于整数]
基本上我发现以下代码在排序上花费了很多时间(与对列表求和而不排序相比):
import System.Random
import Control.DeepSeq
import Data.List (sort)
genlist gen = id $!! sort $!! take (2^22) ((randoms gen)::[Int])
main = do
gen <- newStdGen
putStrLn $ show $ sum $ genlist gen
对列表求和不需要 deepseq,但我正在尝试这样做,但上面的代码对于我正在寻找的指针来说已经足够了。
时间:6 秒(无排序);大约 35 秒(带排序)
内存:约 80 MB(无排序);大约 310 MB(带排序)
注意 1: 内存对我来说是一个比时间更大的问题,因为我手头的任务出现内存不足错误(运行 30 分钟后内存使用量变为 3GB!)
我假设更快的算法也会提供 bettor 内存打印,因此需要 O(n) 时间。
注意 2:我正在寻找 Int64 的快速算法,但其他特定类型的快速算法也会有所帮助。
使用的解决方案:带有未装箱向量的 IntroSort 足以满足我的任务:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Algorithms.Intro as I
sort :: [Int] -> [Int]
sort = V.toList . V.modify I.sort . V.fromList
【问题讨论】:
-
O(n)排序?我想你可以尝试实现spaghetti sort。 -
比较排序的复杂性不能低于
O(n * log n)。由于范围是有限的,您可以使用桶排序(但这不会减少这里的内存使用量;)。您是否尝试过在此基础上构建Data.IntSet和toList? -
使用 Data.IntSet 大约需要 24 秒,所以看起来确实更快,但内存占用为 320 MB ! [
genlist gen = id $!! toList $!! ((fromList $!! take (2^22) ((randoms gen)::[Int])) :: IntSet)] -
@DanielFischer:关于代码黑客或算法的任何想法,将有助于减少内存占用或以某种方式强制垃圾收集?
-
我尝试了
IntMap和Map(由于可能重复,集合并不好),这对空间或时间都没有多大帮助。我能提供的最好的方法是在STUArray上进行快速排序。 快得多,排序只需要很少的内存。然而,最终列表需要大量内存,无论您如何排序。