因此,如果我必须在哈希表或前缀树之间进行选择,那么哪些区别因素会导致我选择一个而不是另一个。从我自己的天真的角度来看,似乎使用trie有一些额外的开销,因为它没有存储为数组但是就运行时而言(假设最长的键是最长的英语单词)它可以基本上是O (1)(就上限而言)。也许最长的英文单词是50个字符?
一旦获得索引,哈希表就会立即查找。然而,散列获得索引的关键似乎很容易接近50步。
有人能为我提供更有经验的观点吗?谢谢!
答案 0 :(得分:112)
尝试的优点:
基础知识:
新操作:
链接结构的优点:
哈希表的优点:
答案 1 :(得分:45)
这一切都取决于你想要解决的问题。如果您只需要插入和查找,请使用哈希表。如果您需要解决更复杂的问题,例如与前缀相关的查询,那么trie可能是更好的解决方案。
答案 2 :(得分:24)
每个人都知道哈希表及其用途,但它不是完全恒定的查找时间,它取决于哈希表的大小,哈希函数的计算复杂性。
在大多数甚至小延迟/可扩展性都很重要的工业场景中(例如:高频交易),创建用于高效查找的巨大哈希表并不是一种优雅的解决方案。您必须关心要在内存中占用的空间进行优化的数据结构,以减少缓存未命中。
一个非常好的例子,其中trie更符合要求的是消息传递中间件。您有一百万订阅者和各种类别的消息发布者(以JMS术语 - 主题或交换),在这种情况下,如果您想根据主题(实际上是字符串)过滤掉消息,您绝对不希望创建哈希表百万主题的百万订阅。更好的方法是将主题存储在trie中,因此当基于主题匹配进行过滤时,其复杂性与主题/订阅/发布者的数量无关(仅取决于字符串的长度)。我喜欢它,因为您可以通过这种数据结构创造性地优化空间要求,从而降低缓存未命中率。
答案 3 :(得分:8)
使用树:
答案 4 :(得分:2)
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)
某些(通常是嵌入式,实时)应用程序要求处理时间与数据无关。在这种情况下,哈希表可以保证已知的执行时间,而特里结构则根据数据而变化。