在线性时间内运行的Haskell中实现反向

时间:2010-08-22 21:06:44

标签: haskell performance complexity-theory

我只是在学习Haskell,很抱歉,如果我的问题很愚蠢。我正在阅读learnyouahaskell.com,现在我正在第5章“递归”。有一个实现标准“反向”功能的例子:

reverse' :: [a] -> [a]  
reverse' [] = []  
reverse' (x:xs) = reverse' xs ++ [x]  

但似乎它在O(N ^ 2)时间运行,而标准反向运行在O(N)(我希望如此)。以下代码说明了这一点:

sum (reverse [1,2..1000000]) -- runs pretty fast
sum (reverse' [1,2..1000000]) -- never finishes

所以,我开始考虑如何更快地实现自己的反向。在命令式语言中很容易做到。也许我需要后续章节中的一些更高级的材料才能做到这一点?欢迎任何提示。

4 个答案:

答案 0 :(得分:24)

可以使用额外的累加器参数有效地实现它,例如本例中fac的第二个参数:

factorial n = fac n 1
  where
    fac 0 r = r
    fac n r = fac (n-1) (r*n)

如果您只是想知道在标准库中如何完成,您还可以look at the source code

答案 1 :(得分:14)

reversePrelude

中定义

您可以将其实施为:

reverse = foldl (flip (:)) []

答案 2 :(得分:7)

reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)

答案 3 :(得分:0)

foldl (\acc x -> x:acc) [] xs

这在O(n)中运行。这个想法非常简单-您可以获取一个空列表(累加器),然后将元素从上到下进行传输。