Tries的缺点

5
我一直在研究Trie,并了解它们的优缺点。由于它们具有恒定的O(m)查询时间(其中m是字符串长度)和提供有序检索以及获取常见前缀等其他优点,因此在许多实际应用程序中(如词典,拼写检查器等),它们非常有用。所以,对我来说,优点非常清楚,但缺点有些令人困惑。
我正在关注的链接是:https://en.wikipedia.org/wiki/Trie 在这里列出的缺点是:
  1. Trie在某些情况下可以比哈希表慢,尤其是当数据直接从硬盘驱动器或其他辅助存储设备上访问时,其中随机访问时间与主存储器相比较高时。
后续问题 - 为什么会涉及到辅助存储?难道Trie不应该存储在主存中吗?如果将它们存储在辅助存储中,则无论如何使用trie都没有用处,因为磁盘访问会始终导致更长的时间。
  1. 一些Trie可能需要比哈希表更多的空间,因为可能为搜索字符串中的每个字符分配内存,而不是像大多数哈希表一样为整个条目分配一个单独的内存块。
后续问题:这是由于Trie会包含更多的引用/指针来连接每个字符到下一个字符,这会消耗比将其作为一个整体字符串存储更多的字节吗?(我从这里的一个答案中得到了这个原因)。可以有人进一步解释一下吗?
我真的很感激在这里获得的帮助。谢谢。
2个回答

5
首先,“常数 O(m) 查找”是没有意义的。在 Trie 中查找时间是 O(m):它取决于您要查找的字符串的长度。
构建良好的哈希表(即良好的哈希函数和合理的负载因子)具有 O(1) 的查找时间。
在假定构造胜任的情况下,在哈希表中查找一个字符串将比在 Trie 中查找快得多。
Trie 和哈希表用于不同的目的。如果您只想查找单词,则哈希表会更快。如果您想查找常见前缀、有序检索或执行类似的操作,则需要 Trie。
哈希表可以非常快地查找单个字符串。就像一匹赛马一样迅速。这就是它所能够做的全部。而另一方面,Trie 是一匹勤劳的工作马,可以做很多事情。它的查找速度永远不会像哈希表那么快,但它可以做许多哈希表无法做的事情。
例如,使用字典查找以“pre”开头的所有单词将需要O(n)的时间,因为您必须搜索所有单词。使用 Trie 只需三次探测就可以找到包含所有这些单词的子树,然后您只需遍历该子树。当然,最坏情况是O(n),但这只有在您的 Trie 中的所有单词都以“pre”开头时才会发生。
虽然确实,如果整个 Trie 都在内存中,则访问磁盘将比较慢,但说基于磁盘的 Trie 不提供任何优势与备选项是错误的。如果数据无法放入内存中,则无论您使用什么数据结构,都需要一些外部(即非内存)存储。当数据在磁盘上时,访问速度变慢并不会从根本上改变 Trie 与哈希表的优缺点。例如,基于磁盘的 Trie 在查找具有特定前缀的所有单词时仍将比基于磁盘的哈希表更快。
哈希表的开销通常是其包含的单词数量的恒定倍数。也就是说,除了存储字符串所需的内存外,还有每个字符串的开销来存储哈希码和字符串之间的映射关系。
Trie 的内存要稍微复杂一些。在最坏情况下,每个字符都有一个节点。所有这些小节点分配开始累加。想象一下包含 200,000 个单词且平均单词长度为五个字符的字典。那就是一百万个节点的开销。
幸运的是,有一些方法可以大大压缩 Trie 而不会失去太多或任何性能。生成的数据结构比朴素构建的 Trie 更小,更适合缓存。

嗨Jim,感谢你的回答。是的,说常数O(m)查找是错误的。除此之外,计算哈希需要O(m)时间,因此哈希查找的总时间应该是O(m)吧?(否则“gaur”和“gaurav”的哈希将相同)。你能在这个部分再解释一下吗? - gaurav jain

1
很久以前有人问过这个问题,但我想补充一下,如果有人在想,一个好的哈希函数应该对于固定内存值(如原始类型或固定长度的原始类型列表)需要花费O(1)时间。通常对所有要进行哈希的值应用相同的逻辑操作(逻辑左移和右移,位运算等)。这些操作无论用于什么值,都需要相同的时间。这使得哈希表更快,而且相对可靠,可以存储使用可预测空间量的值。如果你遍历底层字符数组并只选择间隔的字符来确保始终哈希相同数量的内存,也可以在O(1)时间内对字符串进行哈希。
例如,对于长度为10的字符串,您可以哈希底层字符数组中的10个字符,而对于长度为100的字符串,则基于每个第十个字符进行哈希。
因此,回答你的问题,哈希通常在恒定时间内完成,而从trie中插入或检索则需要O(n)时间,其中n是要插入或检索的值的长度。即使在实践中差异很小,恒定时间具有可预测性的优势。哈希表上的所有操作每次都需要相同的时间,不多不少。但是,对于一个trie(表示威尔士地名的字典),搜索Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch并将其末尾的一个字符更改后,所需的时间要比搜索“a”长得多。系统将在意识到它不在字典中之前遍历整个字符串。Google和其他技术公司倾向于使用漂亮、可预测(但均匀分布)的哈希来避免安全问题。

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