在Trie数据结构中添加单词

时间:2011-03-24 23:23:28

标签: haskell

让Trie数据结构和添加字符串的函数定义如下:

data Trie = Trie { commonness :: Maybe Int
                 , children :: [(Char, Trie)]
                 } deriving (Show, Read, Eq)

-- trie returns an "empty" Trie
trie :: Trie
trie = Trie { commonness = Nothing, children = [] }


-- Add inserts a word to a Trie with a given frequency
-- stored after the last character
add :: String -> Int -> Trie -> Trie
add [] freq tree = tree { commonness = Just freq }
add (x:xs) freq tree = case lookup x (children tree) of
                        Nothing -> tree { children = (x, add xs freq trie):(children tree) }
                        Just subtree -> tree { children = (x, add xs freq subtree):(mydrop x (children tree)) }
                        where
                            mydrop :: Char -> [(Char, Trie)] -> [(Char, Trie)]
                            mydrop _ [] = []
                            mydrop elm (x:xs)
                                | (fst x) == elm = mydrop elm xs
                                | otherwise = x:(mydrop elm xs)

如果角色已经存在于当前级别,则问题是关于更好的算法。我想避免调用mydrop函数和重建子列表。

2 个答案:

答案 0 :(得分:1)

首先,您可以优化mydrop函数本身,以便在找到值时停止遍历列表。

但是,恕我直言,优化整个add函数的唯一方法是合并lookup并将步骤替换为一次遍历。

add' :: String -> Int -> Trie -> Trie
add' [] freq tree = tree { commonness = Just freq }
add' (x:xs) freq tree =
    traverse x (children tree) []
    where
        traverse x [] ts' = tree { children = (x, add' xs freq trie) : ts' }
        traverse x (t:ts) ts' | fst t == x = tree { children = (x, add' xs freq $ snd t) : (ts ++ ts') }
                              | otherwise = traverse x ts (t:ts')

答案 1 :(得分:1)

如果您使用地图而不是关联列表,则可以在alter时使用fromMaybe在查找失败时提供空Trie

import qualified Data.Map as Map
import Data.Map ( Map )
import Data.Maybe ( fromMaybe )

data Trie = Trie { commonness :: Maybe Int
                 , children :: Map Char Trie
                 } deriving (Show, Read, Eq)

-- trie returns an "empty" Trie
trie :: Trie
trie = Trie { commonness = Nothing, children = Map.empty }

-- Add inserts a word to a Trie with a given frequency
-- stored after the last character
add :: String -> Int -> Trie -> Trie
add [] freq tree = tree { commonness = Just freq }
add (x:xs) freq tree =
  tree { children = Map.alter (Just . add xs freq . fromMaybe trie) x $ children tree }