.net 对于只读、无序的唯一字符串集合,执行速度最快的选项是什么?

.net 对于只读、无序的唯一字符串集合,执行速度最快的选项是什么?,.net,performance,data-structures,string,hashset,.net,Performance,Data Structures,String,Hashset,免责声明:我意识到这个问题最明显的答案是HashSet。它是荒谬的快速,它是无序的,它的价值观是独一无二的 但是我只是想知道,因为HashSet是一个可变类,所以它有添加,删除,等等。;因此,我不确定使这些操作成为可能的底层数据结构是否会在读操作时牺牲某些性能——特别是,我关心的是Contains 基本上,我想知道什么是绝对最快的执行数据结构,可以为string类型的对象提供Contains方法。在.NET框架内部或外部 我对各种各样的答案都感兴趣,不管它们的局限性如何。例如,我可以想象某些结构

免责声明:我意识到这个问题最明显的答案是
HashSet
。它是荒谬的快速,它是无序的,它的价值观是独一无二的

但是我只是想知道,因为
HashSet
是一个可变类,所以它有
添加
删除
,等等。;因此,我不确定使这些操作成为可能的底层数据结构是否会在读操作时牺牲某些性能——特别是,我关心的是
Contains

基本上,我想知道什么是绝对最快的执行数据结构,可以为
string
类型的对象提供
Contains
方法。在.NET框架内部或外部

我对各种各样的答案都感兴趣,不管它们的局限性如何。例如,我可以想象某些结构可能被限制为特定长度的字符串,或者可能根据问题域(例如,可能输入值的范围)进行优化,等等。如果它存在,我想听听它

最后一件事:我并没有将此限制为只读数据结构。显然,任何读写数据结构都可以嵌入只读包装器中。我提到“只读”这个词的唯一原因是,我不需要数据结构来允许添加、删除等操作。不过,如果它有这些功能,我不会抱怨


更新

这是一个很好的例子,我正在寻找的东西。由于以下原因,A*显然是一个很大的可能性:
HashSet.Contains
取决于某些
IEqualityComparer
GetHashCode
函数,在.NET中默认为O(n)**。换句话说,必须检查字符串中的每个字符的
HashSet.Contains
以返回
true
false
。对于
Trie
只有
true
的返回值需要O(n)来确定
;返回值
false
可能会更快地返回

这当然是假设。到目前为止,我还没有在.NET中编写或遇到一个Trie实现,它可以在
Contains
中击败
HashSet
(尽管我自己编写的一个实现非常接近字母“a”到“z”)。我只是说,这似乎是可能的

*顺便说一下,这个链接也让我找到了另一个有趣/类似的可能性:。

**这里的“n”指的是字符串的长度。

除了您的疑问,Hashset是最快的集合


没有更快的方法,因为底层哈希表允许O(1)读写访问

哈希容器接近O(1)进行插入和检索,因此从数量级的角度来看,您无法获得比这更好的方法

在散列容器中,随着时间的推移,您的性能将与两件事相关:您的散列函数提供的分布有多好,以及它的计算速度有多快。这些都是不等价的——一个分布不好的函数(最终会导致大量冲突)比一个速度较慢但分布更好的散列函数对性能的影响要大得多


因此,如果你能想出一个计算速度非常快的完美散列函数,那将是一个改进。以特定方式约束数据可能会使这更容易。但是,你很可能会发现,无论你想出什么,都不会像已经存在的那样好

适合于执行
包含的
,尤其是有限字母表中的字符串。给定一个字符串s,trie上Contains的时间复杂度为O(| s |)(| s |=s的长度),这是最佳的。

哈希表在查找时摊销为O(1)。再好不过了,O(1/n)算法是永动机。只有两件事会让他们表现不好:

  • 一个糟糕的散列函数,会导致许多冲突。最坏的情况是将查找退化为O(n)。字符串不会有问题,它们散列得非常好。GetHashCode()做得非常好
  • 由于早期添加的许多已删除项而发生严重变异的集合。这会导致迭代器跳过许多空哈希桶。从技术上讲,降解为O(n)是可能的,尽管非常罕见。一个简单的解决方法是通过重新分配引用来重建集合(比如table=newhashset(table);)

这种问题很少见。您不预先为它们设计(哈希函数除外),只有在检测到程序的性能问题时才开始考虑它们。

不过可能会有一个更快的集合,例如,一个总是两倍快的集合。O(1)并不意味着“尽可能快”;这只是意味着成本不会随着输入的大小(在本例中,是集合的大小)而增加。不过,我当然愿意承认你是对的。但是我希望了解一些其他的选择。是的,你是对的,但是直接访问——一个哈希表提供的——是无需担心的最快的访问方法。我自己也在想类似的事情。显然,这似乎是一个不错的选择:固定在字符“a”到“z”(我尝试了一个不区分大小写的实现)上,我能够获得与
哈希集
一样快的性能。不过,显然,如果它的速度也一样快,那么它就不值得真正实现。不过,尽管存在局限性,这显然是一个有希望的选择。“我必须进一步探索它。”丹。我很惊讶它没有比HashSet快。HashSet/string的哈希函数是否不查看字符串中的所有字符?无论如何,我不确定你做了什么测试,但我想这与你有关