实现字典的最佳数据结构是什么?

74
什么是存储字典中所有单词的最佳数据结构?我所能想到的最好方法是使用一个 HashMap ,该映射将映射到 HashTable 。基本上,根据第一个字符,我们将获取相关的 HashTable ,然后使用此表,我们可以添加以该字符开头的单词。然后,我们将根据字符串选择一个好的哈希函数。
是否有更好的方法呢?
1个回答

154

根据你的需求,有很多好的数据结构可供选择。

如果你只是想存储单词并询问“这个单词是否存在?”,一个标准的哈希表,不需要其他花哨的机制,是一个合理的选择。如果该词预先固定,请考虑使用完美哈希表以获得优秀的性能和空间利用率。

如果您想要检查给定前缀是否存在,并支持快速查找,则Trie是一个很好的选择,但可能会有一些空间效率低的问题。它还支持快速插入或删除。它还允许按字母顺序进行迭代,哈希表则无法提供。这本质上是你在答案中描述的结构,但根据用例不同,可能有更好的Trie表示方式。

如果除了上面提到的内容之外,你确信单词列表是固定的,那么请考虑使用DAWG(有向无环图)(directed acyclic word graph),它实质上是语言的最小状态DFA。它比Trie小得多,但支持许多相同的操作。

如果你想要Trie一样的行为,但不想付出巨大的空间代价,三叉搜索树是另一个可行的选择,以及基数树。这些结构非常不同,但在不同情况下可能比Trie更好。

如果空间是一个问题,但你想使用trie数据结构,可以考虑使用succinct trie表示法,它的查找速度较慢,但几乎在理论上达到了最优的空间利用率。该链接讨论了它在JavaScript中的使用,作为传输大量数据的简便方式。另一种紧凑的表示方法是double-array trie,不过我对它了解甚少。

如果要将字典用于拼写检查等需要查找相似单词的操作,则应考虑使用BK-tree这种优秀的数据结构。


3
一条评论:虽然它可以节省一些空间,但有点不太高效,是吗? - Gert Arnold
2
@Pavan- Trie(字典树)中的每个节点已经存储了一个位,表示该节点是否为单词。您可以用指向包含该单词定义的字符串的指针来替换该位(如果存在该单词的定义),或者用null(如果不是单词)来表示。 - templatetypedef
1
@templatetypedef 如果我需要查找同义词怎么办? - Vivek Vardhan
@templatetypedef 如果 Trie 数据结构存储了要查找的单词所在位置,并且可以指向包含意义或同义词的列表或某些数据,则正确。 - Krishna Oza
1
根据需求,一组布隆过滤器可以实现非常快速的查找(有小概率出现误判),同时也非常节省空间。 - Adrian McCarthy
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接