我正在尝试在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#中实现此数据结构的任何其他建议,我知道我必须做很多错误,因为我对这种语言很新。我知道例如单词插入函数是有缺陷的,因为它不检查列表是否为空,因此它过早结束。当我到达那里时,我想过那座桥。
提前谢谢
提前谢谢
答案 0 :(得分:4)
您可能无法触发断点,因为您没有完全应用insertWords
:它需要两个curried参数,但您只传递单个参数wordChars
。也许你的意思是定义这样的Trie
类型吗?
type Trie(inner : TrieNode) =
member this.InsertWord(wordChars:char list) = TrieFunctions.insertWord wordChars inner
好吧,你可以在[]
中包装所有的返回值,使它们成为单例列表,然后不将递归调用包装到insertWords
。但是,您的算法似乎有可能出现问题(无论哪种方式),因为您只获得单例列表......
请注意,您现在完全放弃现有的subnodes
列表 - 如果您想要附加到其前面,请改用(insertWord wordChards.Tail node)::subnodes
。但是,有时您会想要替换现有条目而不是添加新条目,这将需要更多努力。
有几个问题。以下是一些可以帮助您入门的内容:
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