如何在哈希表和Trie(前缀树)之间进行选择?

时间:2008-10-29 05:19:05

标签: algorithm data-structures hashtable trie

因此,如果我必须在哈希表或前缀树之间进行选择,那么哪些区别因素会导致我选择一个而不是另一个。从我自己的天真的角度来看,似乎使用trie有一些额外的开销,因为它没有存储为数组但是就运行时而言(假设最长的键是最长的英语单词)它可以基本上是O (1)(就上限而言)。也许最长的英文单词是50个字符?

一旦获得索引,哈希表就会立即查找。然而,散列获得索引的关键似乎很容易接近50步。

有人能为我提供更有经验的观点吗?谢谢!

8 个答案:

答案 0 :(得分:112)

尝试的优点:

基础知识:

  • 可预测的O(k)查找时间,其中k是密钥的大小
  • 如果不存在,查找可能需要不到k的时间
  • 支持有序遍历
  • 不需要哈希函数
  • 删除很简单

新操作:

  • 您可以快速查找密钥的前缀,枚举具有给定前缀的所有条目等。

链接结构的优点:

  • 如果有许多公共前缀,则需要共享它们所需的空间。
  • 不可变尝试可以共享结构。您可以构建一个新的,只在一个分支上有所不同,而在其他地方指向旧的trie,而不是更新trie。这对于并发,表的多个同时版本等非常有用。
  • 不可变的特里是可压缩的。也就是说,它也可以通过哈希值来共享后缀上的结构。

哈希表的优点:

  • 每个人都知道哈希表,对吗?您的系统已经有一个很好的优化实现,比大多数目的都要快。
  • 您的钥匙不需要任何特殊结构。
  • 比明显的链接结构更节省空间(见下面的评论

答案 1 :(得分:45)

这一切都取决于你想要解决的问题。如果您只需要插入和查找,请使用哈希表。如果您需要解决更复杂的问题,例如与前缀相关的查询,那么trie可能是更好的解决方案。

答案 2 :(得分:24)

每个人都知道哈希表及其用途,但它不是完全恒定的查找时间,它取决于哈希表的大小,哈希函数的计算复杂性。

在大多数甚至小延迟/可扩展性都很重要的工业场景中(例如:高频交易),创建用于高效查找的巨大哈希表并不是一种优雅的解决方案。您必须关心要在内存中占用的空间进行优化的数据结构,以减少缓存未命中。

一个非常好的例子,其中trie更符合要求的是消息传递中间件。您有一百万订阅者和各种类别的消息发布者(以JMS术语 - 主题或交换),在这种情况下,如果您想根据主题(实际上是字符串)过滤掉消息,您绝对不希望创建哈希表百万主题的百万订阅。更好的方法是将主题存储在trie中,因此当基于主题匹配进行过滤时,其复杂性与主题/订阅/发布者的数量无关(仅取决于字符串的长度)。我喜欢它,因为您可以通过这种数据结构创造性地优化空间要求,从而降低缓存未命中率。

答案 3 :(得分:8)

使用树:

  1. 如果您需要自动完成功能
  2. 找到以'a'或'ax'开头的所有单词。
  3. 后缀树是树的特殊形式。后缀树有一大堆优点,哈希无法覆盖。

答案 4 :(得分:2)

与基本 Trie 实施相比,

HashTable 实施具有空间效率。但是对于字符串,在大多数实际应用中都需要排序。但是HashTable完全扰乱了词法秩序。现在,如果您的应用程序正在执行基于词法顺序的操作(如部分搜索,具有给定前缀的所有字符串,所有按排序顺序排列的单词),则应使用Tries。对于仅查找,应该使用HashTable(可以说,它提供了最少的查找时间)。

P.S。:除此之外,三元搜索树(TST)将是一个很好的选择。它的查找时间不仅仅是HashTable,而且在所有其他操作中都具有时间效率。此外,它比尝试更节省空间。

答案 5 :(得分:1)

有些东西我没有看到任何人明确提到我认为重要的是要记住。散列表和各种尝试通常都有O(k)次操作,其中k是以位为单位的字符串长度(或等效于字符)。

这假设你有一个很好的哈希函数。如果你不希望“farm”和“farm animals”散列到相同的值,那么hash函数将不得不使用密钥的所有位,因此散列“farm animals”应该花费大约两倍的时间。 “farm”(除非你处于某种滚动哈希方案中,但是有一些类似的操作保存方案也有尝试)。通过香草尝试,很明显为什么插入“农场动物”将花费大约两倍于“农场”的时间。从长远来看,压缩尝试也是如此。

答案 6 :(得分:1)

trie上的插入和查找与输入字符串O(s)的长度呈线性关系。

哈希将为您提供查找和插入的O(1),但首先您必须根据输入字符串计算哈希值,该字符串也是O(s)。

结论,渐近时间复杂度在两种情况下都是线性的。

从数据的角度来看,trie有一些额外的开销,但你可以选择一个压缩的trie,它会或多或少地与你的哈希表联系起来。

打破领带问自己这个问题:我是否只需要查找完整的单词?或者我是否需要返回与前缀匹配的所有单词? (如在预测文本输入系统中)。对于第一种情况,请寻找哈希值。它更简单,更清晰。更容易测试和维护。对于更加精心设计的前缀或后缀很重要的用例,请选择特里。

如果你这样做只是为了好玩,实施一个特里会使周日下午得到很好的利用。

答案 7 :(得分:-1)

某些(通常是嵌入式,实时)应用程序要求处理时间与数据无关。在这种情况下,哈希表可以保证已知的执行时间,而特里结构则根据数据而变化。