我是新的Haskell,我试图实现一些已知的算法。
我已经在字符串上实现了合并排序。与C和Java实现相比,我对我的Haskell实现的性能有点失望。在我的机器上(Ubuntu Linux,1.8千兆赫),C语言(gcc 4.3.3)在1.85秒内对1 000 000个字符串进行排序,Java(Java SE 1.6.0_14)在3.68年代, haskell (GHC 6.8.2)在25.89s内.用较大的输入(10 000 000个字符串),C需要21.81秒,Java需要59.68秒,Haskell开始交换,我宁愿在几分钟后停止程序。
由于我是Haskell的新手,我很想知道我的实现是否可以使时间/空间效率更高。
提前感谢您的任何提示Giorgio
我的实现:
merge :: [String] -> [String] -> [String]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x < y
then x : (merge xs (y:ys))
else y : (merge (x:xs) ys)
mergeSort :: [String] -> [String]
mergeSort xs = if (l < 2)
then xs
else merge h t
where l = length xs
n = l `div` 2
s = splitAt n xs
h = mergeSort (fst s)
t = mergeSort (snd s)
4条答案
按热度按时间piv4azn71#
尝试此版本:
1.坏主意是先拆分列表。而不是只做一个成员列表的列表。 haskell 很懒,它会在正确的时间完成。
1.然后合并成对的列表,直到只有一个列表。
bprjcwpo2#
在Haskell中,字符串是一个懒惰的字符列表,它的开销和任何其他列表一样。如果我记得2004年Simon佩顿Jones的给予,GHC中的空间开销是每个字符40字节。对于一个苹果对苹果的比较,你可能应该排序
Data.ByteString
,它的设计是为了提供与其他语言相当的性能。hgncfbus3#
更好的方法是拆分列表,以避免CesarB指出的问题:
编辑:已修复。
bzzcjhmw4#
我不确定这是否是您的问题的原因,但请记住列表是一种顺序数据结构,特别是
length xs
和splitAt n xs
都需要花费与列表长度(O(n)
)成比例的时间。在C和Java中,您最有可能使用数组,这两种操作都需要恒定的时间(
O(1)
)。编辑:回答你关于如何使它更有效的问题,你也可以在Haskell中使用数组。