开发者

adding word to Trie data structure

let the Trie data structure and the function to add a string are defined as follows:

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)

The question is about a better algorithm in case the character already does exist in the current level. I'd like to avoid call of mydrop function a开发者_Go百科nd reconstruction of the list of children.


First of all you may optimize mydrop function itself in order to stop traversing the list when found the value.

But, IMHO, the only way to optimize the whole add function is to merge lookup and replacing steps into the one traversal.

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')


If you use a Map instead of an association list, you can use alter with fromMaybe to provide an empty Trie when the lookup fails:

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 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜