所以我已经完成了Lempel-Ziv压缩/解压缩,但与C ++相比,它的速度令人难以置信, 我试过了 http://norvig.com/big.txt文件,但我的程序无法处理它,而在C ++中它只用了1秒钟。你们中的任何人都可以查看我的代码并告诉我是否存在一些明显的缺陷吗?
import System.IO
import Control.Monad
import qualified Data.Map as Map
import Debug.Trace
main = do
contents <- readFile "plik.txt"
let compressed = reverse $ compress contents Map.empty 1 "" []
let decompressed = reverse $ decompress compressed Map.empty 1 ""
--print $ contents
print $ length compressed
print $ length decompressed
--print $ contents == decompressed
compress :: String -> Map.Map String Int -> Int -> String -> [(Int,Char)]-> [(Int,Char)]
compress (s:x) m i c out = do
if Map.member (c++[s]) m == False
then do
if c == ""
then do
let newMap = Map.insert [s] i m
compress x newMap (i+1) c ((0,s):out)
else do
let newMap = Map.insert (c++[s]) i m
compress x newMap (i+1) "" ((newMap Map.! c, s):out)
else compress x m i (c++[s]) out
compress s m i c out = compress2 out
compress2 :: [(Int,Char)]-> [(Int,Char)]
compress2 out = trace("COMPRESSION FINISHED") out
decompress :: [(Int,Char)] -> Map.Map Int String -> Int -> String -> String
decompress (s:x) m i out = do
if fst s == 0
then do
let newMap = Map.insert i [snd s] m
decompress x newMap (i+1) ((snd s):out)
else do
let newMap = Map.insert i ((m Map.! fst s)++[snd s]) m
decompress x newMap (i+1) ((snd s):(reverse (newMap Map.! fst s))++out)
decompress s m i out = out
decompress2 :: String -> String
decompress2 out = trace("DECOMPRESSION FINISHED") out
答案 0 :(得分:1)
其他人已在评论中说过:
避免使用String
;它使用了大量的RAM,处理速度很慢。使用ByteString
(如果您希望处理原始二进制数据)或Text
(如果您期望使用Unicode文本)。
不要附加到列表中。 (String
也是一个列表 - 但首先不要使用String
。)如果很容易,请提前添加。如果不是,请根据需要使用Data.Sequence
,Data.Set
或Data.Map
。或者甚至可能是Text
,ByteString
或Vector
。
如果你看到Haskell程序真的很慢并且使用了大量的RAM,即使输入和输出文件很小,你可能也有些东西太懒了。
作为一个例子,我有一个程序来产生一个字节直方图。花了大约20分钟消耗了8 GB的RAM。我将数据构造函数更改为严格,只需向其添加一个!
即可。现在该程序只需几分之一秒!如果你弄错了,懒惰可以产生一个荒谬的巨大差异。
查看您发布的代码,这可能涵盖了所有内容。 (我不确定你已经尝试过哪些改变以及你现在所处的位置。)