Data structures 要添加/查找/保留字符串计数的数据结构?

Data structures 要添加/查找/保留字符串计数的数据结构?,data-structures,hashtable,trie,Data Structures,Hashtable,Trie,我试图找出什么样的数据结构可以快速支持以下操作: 添加一个字符串(如果不存在,则添加该字符串;如果存在,则为该单词增加一个计数器) 计算给定的字符串(按字符串查找,然后读取计数器) 我在争论哈希表还是trie。根据我的理解,只要避免冲突,哈希表就可以快速查找和添加。如果我不能提前知道我的输入,trie是一种更好的方法吗?任何一种都相当快 没有必要完全避免碰撞 从性能上看,通常哈希表比树快,但我怀疑现实生活中的程序是否因为使用树而不是HT而运行得太慢,并且有些树比某些哈希表快 我们还能说什么呢

我试图找出什么样的数据结构可以快速支持以下操作:

  • 添加一个字符串(如果不存在,则添加该字符串;如果存在,则为该单词增加一个计数器)
  • 计算给定的字符串(按字符串查找,然后读取计数器)

我在争论哈希表还是trie。根据我的理解,只要避免冲突,哈希表就可以快速查找和添加。如果我不能提前知道我的输入,trie是一种更好的方法吗?

任何一种都相当快

没有必要完全避免碰撞

从性能上看,通常哈希表比树快,但我怀疑现实生活中的程序是否因为使用树而不是HT而运行得太慢,并且有些树比某些哈希表快

我们还能说什么呢,哈希表比树更常见


复杂树的一个优点是它们具有可预测的访问时间。对于哈希表和简单的二叉树,您看到的性能取决于数据,而对于HT性能,很大程度上取决于实现的质量及其相对于数据集大小的配置。

这实际上取决于您将用作“键”的字符串的类型。如果您使用的是高度可变的字符串,加上您的字符串没有一个好的哈希算法,那么trie的性能可能会优于哈希

但是,如果有一个好的散列,查找将比trie更快。(给出一个非常糟糕的散列,情况正好相反。)如果你不知道自己的输入,但确实有一个不错的散列算法,我个人更喜欢使用散列


此外,大多数现代语言/框架都有非常好的哈希算法,所以很有可能,您可以使用一个哈希实现一个很好的查找,只需很少的工作,这将非常好地执行;只有当前缀很重要时,它们才有趣。哈希表比较简单,通常是语言标准库的一部分,如果不是语言本身的一部分(Ruby、Python等)。在Ruby中,有一种非常简单的方法可以做到这一点:

strings = %w(some words that may be repeated repeated)
counts = Hash.new(0)
strings.each { |s| counts[s] += 1 }
#counts => {"words"=>1, "be"=>1, "repeated"=>2, "may"=>1, "that"=>1, "some"=>1}
附录
对于C++,你可以使用.< /p>如果我从头开始设计这个数据结构,会有什么建议。这是一个项目,我们可以把它从任何数据结构,但我们必须设计一切使用C++。该项目根据添加/搜索方法的速度进行分级。可能会有数十万个随机字符串的输入。我没有任何实现哈希表或尝试的经验,所以我想知道哪一个更好。Trie更容易实现。哈希表可能更容易“正确”,特别是因为有很多样本。很有可能,在分数方面,你会用哈希表做得更好——只要确保尝试得到一个好的字符串哈希算法(因为这会使添加/删除非常快)。我只是想到了一些其他的东西——如果你不能控制要添加或删除的字符串,请使用哈希。如果你给Trie输入“坏”字符串,它的降解会非常严重。。。因此,如果字符串不好,插入/删除速度可能非常差。只有当你有散列冲突时,散列才会降级,这在好的散列算法中是不会发生的?另外,如果开始有太多的输入,您认为必须增加哈希表有什么缺点吗?这取决于您的实现。例如,在大多数实现中,如果字符串的开头相同,而只有“end”部分不同,Trie的性能就很差。trie中共享的“prefix”值基本上使其向O(n)移动以进行查找,“n”是字符串的长度。以类似值开头的长字符串的性能非常差。另一方面,散列并不重要——更改任何值都会调整散列,因此一个好的散列算法可以防止这些类型的递减问题。