【发布时间】:2011-03-11 19:41:51
【问题描述】:
我还在学习 Haskell,我编写了以下基数排序函数。它似乎工作正常,但问题是它的内存效率相当低。如果使用 ghc 编译,内存已经超过 500MB,输入列表大小为 10000 个元素。
所以我想问您如何改进以下算法/代码以使其在速度和内存方面更有效。最好的起点是什么?
import System.Random
-- radixsort for positive integers. uses 10 buckets
radixsort :: [Int] -> [Int]
radixsort [] = []
radixsort xs =
-- given the data, get the number of passes that are required for sorting
-- the largest integer
let maxPos = floor ((log (fromIntegral (foldl max 0 xs)) / log 10) + 1)
-- start sorting from digit on position 0 (lowest position) to position 'maxPos'
radixsort' ys pos
| pos < 0 = ys
| otherwise = let sortedYs = radixsort' ys (pos - 1)
newBuckets = radixsort'' sortedYs [[] | i <- [1..10]] pos
in [element | bucket <- newBuckets, element <- bucket]
-- given empty buckets, digit position and list, sort the values into
-- buckets
radixsort'' [] buckets _ = buckets
radixsort'' (y:ys) buckets pos =
let digit = div (mod y (10 ^ (pos + 1))) (10 ^ pos)
(bucketsBegin, bucketsEnd) = splitAt digit buckets
bucket = head bucketsEnd
newBucket = bucket ++ [y]
in radixsort'' ys (bucketsBegin ++ [newBucket] ++ (tail bucketsEnd)) pos
in radixsort' xs maxPos
-- get an random array given an seed
getRandIntArray :: Int -> [Int]
getRandIntArray seed = (randomRs (0, div (maxBound :: Int) 2) (mkStdGen seed))
main = do
value <- (\x -> return x ) (length (radixsort (take 10000 (getRandIntArray 0))))
print value
【问题讨论】:
-
你考虑过使用 IO monad 中的数组吗?
-
谢谢,当我对 Haskell 基础知识感到更熟悉时,我一定会检查其他数据类型。
-
在
maxPos中,您应该使用foldl'而不是foldl。另外,floor (x + 1)不是更好地表达为ceiling x吗? -
您可以考虑对 Haskell 数组上现有的基数排序进行基准测试:hackage.haskell.org/packages/archive/vector-algorithms/0.4/doc/…
-
@Gabe ST 更好,因为它是准纯的。
标签: optimization haskell radix-sort