‘适当’集合用于在C#.NET中的O(1)时间内获取项目?

如果我存储了一堆字符串值并且我希望能够在O(1)之后找到它们,我经常做的事情是:

foreach (String value in someStringCollection) { someDictionary.Add(value, String.Empty); } 

这样,我可以在以后轻松对这些字符串值执行常量时间查找,例如:

 if (someDictionary.containsKey(someKey)) { // etc } 

但是,我觉得我在制作值String.Empty时作弊。 我应该使用更合适的.NET集合吗?

如果您使用的是.Net 3.5,请尝试使用HashSet 。 如果您不使用.Net 3.5,请尝试使用C5 。 否则你当前的方法是可以的(bole,因为@leppie建议更好,或者不像@JonSkeet建议的那样,dun dun dun!)。

 HashSet stringSet = new HashSet(someStringCollection); if (stringSet.Contains(someString)) { ... } 

你可以在.NET 3.5中使用HashSet ,否则我会坚持你当前的方法(实际上我更喜欢Dictionary但是并不总是那么奢侈)。

您可能想要添加的内容是哈希的初始大小 。 我不确定C#的实现方式是否与Java不同,但它通常有一些默认大小,如果你添加更多,它会扩展集合。 然而,适当大小的散列对于实现尽可能接近O(1)是重要的。 目标是在每个桶中准确地输入1个条目,而不是真的很大。 如果你进行一些搜索,我知道有一个建议的比例来调整哈希表的大小,假设你事先知道你将添加多少元素。 例如,类似“哈希的大小应该是要添加的元素数量的1.8倍”(不是实际比率,只是一个例子)。

来自维基百科 :

使用良好的哈希函数,哈希表通常可以包含与表槽一样多的元素的70%-80%,并且仍然表现良好。 根据冲突解决机制,随着更多元素的添加,性能可能会逐渐或显着下降。 为了解决这个问题,当负载因子超过某个阈值时,需要分配一个新的更大的表,并将原始表的所有内容添加到这个新表中。 例如,在Java的HashMap类中,默认的加载因子阈值是0.75。

我应该提出一个问题,因为我经常看到这个问题。 是什么让你认为词典是O(1)? 从技术上讲,唯一可能像O(1)这样的东西是使用整数索引值访问标准的整数索引固定绑定数组(在这种方式中实现的数组中没有查找)。

假设如果它看起来像数组引用那么当“索引”是必须以某种方式查找的值时它是O(1),但是在幕后,意味着它不可能是O(1)方案,除非你幸运的是获得一个没有碰撞的数据的哈希函数(可能还有很多浪费的单元格)。

我看到了这些问题,我甚至看到了声称O(1)的答案[不是关于这个特定的问题,但我看起来似乎是这些问题],没有任何理由或解释确保O(1)实际实现的要求。

嗯,我想这是一个不错的问题。 我在这里发表这篇评论后会这样做。