【发布时间】:2015-02-16 01:18:01
【问题描述】:
我对 Haskell 完全陌生,正在努力学习。我决定编写一个简短的(不平衡的)二叉搜索树代码来开始。它将文本分解为单词,将单词添加到二叉树(丢弃重复项),然后遍历树以打印出文本中单词的排序列表。
data BinTree t = ExternalNode
| InternalNode (BinTree t) t (BinTree t)
treeInsert :: Ord t => BinTree t -> t -> BinTree t
treeInsert ExternalNode w = InternalNode ExternalNode w ExternalNode
treeInsert tree@(InternalNode left v right) w
| w == v = tree
| w < v = InternalNode (treeInsert left w) v right
| otherwise = InternalNode left v (treeInsert right w)
treeFromList :: Ord t => [t] -> BinTree t
treeFromList l = go ExternalNode l
where
go acc [] = acc
go acc (x : xs) = acc `seq` go (treeInsert acc x) xs
inOrderList :: BinTree t -> [t]
inOrderList ExternalNode = []
inOrderList (InternalNode left v right) = (inOrderList left) ++ [ v ] ++ (inOrderList right)
main :: IO ()
main = do
tmp <- readFile "words.txt"
printList . inOrderList . treeFromList $ words tmp
where
printList [] = return ()
printList (x : xs) = do
putStrLn x
printList xs
该程序适用于小文本。然后我给它喂了詹姆士国王圣经。它崩溃抱怨堆栈大小太小。我必须将堆栈大小增加到 200M 才能使其工作!
我的错误在哪里?我想这可能与懒惰的评估搞砸了一些事情有关。无论如何,问题不在于二叉搜索树的深度,对于圣经示例,二叉搜索树的深度仅为 163。
【问题讨论】:
-
“仅”163?如果树是平衡的,那就是 2^164-1 个元素。
-
您能否提供您使用的文件
words.txt的链接? this version of the KJV 是否与您的相媲美 -
使用 ghc 7.8.3 我能够运行只有 27M 堆栈的程序:
bintree +RTS -K27M(使用ghc -O2 bintree.hs -rtsopts编译后) -
好吧,
String每个字符使用大约十几个字节。如果你的树的任何分支由于懒惰而未被评估,那可能是六个字节左右...... -
确实,如果您关心性能,
String通常不是您想要的——使用Text。如果你绝对只需要 ASCII,你甚至可以使用ByteString,但这是不受欢迎的。
标签: haskell tree lazy-evaluation evaluation