新手F#trie实施出错了

时间:2011-02-15 20:37:29

标签: f# trie

我正在尝试在F#中实现trie数据结构。 我有一些问题。 我无法调试单词插入功能。我在这个函数中的任何断点都没有遇到崩溃但我没有看到任何错误。 如果我把事情做得对,我也有严重的疑虑。 无论如何这里是代码:

type TrieNode =
    | SubNodes of char * bool * TrieNode list
    | Nil
    member this.Char = match this with | Nil -> ' '
                                       | SubNodes(c,weh,subnodes) -> c
    member this.GetChild(c:char) = match this with  | Nil -> []
                                                    | SubNodes(c,weh,subnodes) ->[ (List.filter(fun (this:TrieNode) -> this.Char = c) subnodes).Head ]

    member this.AWordEndsHere = match this with | Nil -> false
                                                | SubNodes(c,weh,subnodes) -> weh
module TrieFunctions = 
    let rec insertWord (wordChars:char list) = function
        | Nil -> SubNodes(wordChars.Head, false, [])
        | SubNodes(c, weh, subnodes) as node ->
            let child = node.GetChild(wordChars.Head)
            if child = [] then 
                SubNodes(wordChars.Head,false,[insertWord wordChars.Tail node])
            else
                SubNodes(wordChars.Head,false,[insertWord wordChars.Tail child.Head])


type Trie(inner : TrieNode) =

    member this.InsertWord(wordChars:char list) = TrieFunctions.insertWord(wordChars)


  let trie = Trie(SubNodes(' ',false,List.empty)).InsertWord(['g';'i';'g';'i'])

所以我的问题是:
1.如何获得insertWord函数的调试权限?我为什么不现在得到它?为什么我没有看到错误?
2.如何使函数插入单词返回一个TrieNode对象列表,这样我就不必围绕方括号(“[”,“]”)包围调用。我认为这是一个错误 3.您可以向我提供有关在F#中实现此数据结构的任何其他建议,我知道我必须做很多错误,因为我对这种语言很新。我知道例如单词插入函数是有缺陷的,因为它不检查列表是否为空,因此它过早结束。当我到达那里时,我想过那座桥。

提前谢谢

提前谢谢

2 个答案:

答案 0 :(得分:4)

  1. 您可能无法触发断点,因为您没有完全应用insertWords:它需要两个curried参数,但您只传递单个参数wordChars。也许你的意思是定义这样的Trie类型吗?

    type Trie(inner : TrieNode) =
      member this.InsertWord(wordChars:char list) = TrieFunctions.insertWord wordChars inner
    
  2. 好吧,你可以在[]中包装所有的返回值,使它们成为单例列表,然后不将递归调用包装到insertWords。但是,您的算法似乎有可能出现问题(无论哪种方式),因为您只获得单例列表......

    请注意,您现在完全放弃现有的subnodes列表 - 如果您想要附加到其前面,请改用(insertWord wordChards.Tail node)::subnodes。但是,有时您会想要替换现有条目而不是添加新条目,这将需要更多努力。

  3. 有几个问题。以下是一些可以帮助您入门的内容:

    • 尽量避免使用Head,特别是因为您在调用时并不总是知道列表是非空的。
    • 当您将一个单词插入空Trie时,除了第一个字符外,您将丢弃所有字符!同样,您也需要重新考虑递归调用。
    • 更重要的是,您的TrieNode类型存在一些问题。你能否写出你希望看到哪个只包含两个单词"in""to"的结果trie?

答案 1 :(得分:1)

关于你的第一个问题,正如@kvb所说,你正在部分应用insertWord。在定义它时,您指定了一个显式参数wordChars,并且通过使用function构造进行模式匹配,您基本上添加了类型TrieNode的第二个参数,因此您的函数最终会得到以下结果签名:

insertWord : char list -> TrieNode -> TrieNode

因为在你调用InsertWord(它只是insertWord的包装器)时你只提供一个参数(一个字符列表),所以函数不会被调用,但是你会得到一个函数期待TrieNode回来。 InsertWord的签名清楚地说明了这一点:

InsertWord : wordChars:char list -> (TrieNode -> TrieNode)

请注意括号。

您可能希望在您的案例中提供Nil,因为从概念上讲,您正在扩展一个空的特里:

let trie = Trie(SubNodes(' ',false,List.empty)).InsertWord(['g';'i';'g';'i']) Nil

您可以在此处找到trie结构的示例实现:http://lepensemoi.free.fr/index.php/2009/10/15/trie-and-anagrams-with-f