SortedSet<T> 与 HashSet<T>
Posted
技术标签:
【中文标题】SortedSet<T> 与 HashSet<T>【英文标题】:SortedSet<T> vs HashSet<T> 【发布时间】:2011-06-05 02:19:21 【问题描述】:我的问题是,当我们拥有SortedSet<T>
时,HashSet<T>
的需要是什么!所有 HashSet 的方法都在 SortedSet 中可用,而且 SortedSet 的优势在于它已经以排序的方式提供了集合!即使这样 HashSet 也存在。那它有什么用呢?
【问题讨论】:
HashSetHashSet<T>
时需要知道的一个有用(有时)的事情:即使在 64 位应用程序中,它也可以存储多达 ~4800 万个 Guid
s 或 long
s 或 ~95数百万int
s,然后抛出OutOfMemoryException
。 SortedSet<T>
似乎有更高的容量限制。如果出于某种原因您需要在内存中保留数亿个项目,HashSet<T>
可能不是一个好的选择。
@Vladimir:根据文档,“对于非常大的 HashSetHashSet<T>
和 SortedSet<T>
都在实现 interface ISet<T>
,这是一个包含独特元素的数据结构。
它们之间的主要区别在于它们用于存储数据的底层数据结构。
HashSet<T>
使用哈希表,而SortedSet<T>
使用红黑树,这是一种平衡二叉树。
使用哈希表的HashSet<T>
执行基本操作(即添加、删除、搜索)的速度比SortedSet<T>
快,因为HashSet<T>
的复杂度为 O(1),这意味着它将执行独立于在恒定时间段内输入数据的大小,而SortedSet<T>
的复杂度为 log(N),这意味着取决于输入的大小,它将执行对数的基本操作。例如,如果输入数据的大小为 1,000,则程序分 10 步执行基本操作,如果输入数据为 1,000,000,则程序分 20 步执行基本操作。
结论:使用HashSet<T>
如果您不需要对元素进行排序否则使用SortedSet<T>
。这意味着使用HashSet<T>
是首选,除非您需要排序。
【讨论】:
这是这个问题下的最佳答案。非常有用,谢谢分享。【参考方案2】:这是关于为工作选择正确的工具。取决于您使用收藏的方式。
This page 有一个很好的表格,详细说明了各种集合类之间的差异。
以下是该表中关于您所询问的集合的摘录:
集合订购连续存储?直接访问?查找效率 操纵效率 SortedSet Sorted No Via Key Key:O(log n) O(log n) HashSet Unordered Yes Via Key Key:O(1) O(1)【讨论】:
我看到您链接到的文章将基于 Hashtable 的类型(Dictionary<TKey,TValue>
和 HashSet<T>
)列为“连续” - 但它们不会将密钥连续存储在其内部(即通常sparse) 键数组,而 SortedDictionary
和 SortedSet
使用密集树,所以我很惊讶这篇文章没有涉及不同数量的键的 SortedSet 与 HashSet 的内存使用情况。
@Svisstack 从技术上讲,在哈希集中查找是 O(m),其中 m 是哈希函数的平均哈希冲突率。对于一个完全均匀分布的散列函数,这导致查找为 O(1),对于一个总是碰撞的完全错误的散列函数,这将使查找 O(n),其中 n 是集合的大小。您通常只使用具有良好散列函数的类型的散列集,在大多数实际情况下使其成为 O(1)。是什么让你认为它是 O(log(n))?
@Svisstack “你不能假设你的散列函数很好”好吧,你可以。大多数人都这样做。如果你不能正确地散列对象你不应该在基于散列的集合中使用它。有些人会在这个符号上加上一个星号,表示它假设一个好的散列,因为你是对的,它是在陈述 O(1) 时做出的假设,即使它是一个有效的假设。 “如果你有碰撞,那么你基本上有 Set” 不,那么你有一个列表。通过它进行搜索需要线性搜索,即 O(m),其中 m 是该哈希桶中的项目数。
@Svisstack 很少 很少有数据结构被设计成在项目数超过 int.MaxValue 时能够正常工作,甚至根本不能正常工作。说如果你有比 int.MaxValue 更多的项目操作不再是 O(1) 是非常没有意义的,因为它从一开始就不是受支持的用例,所以它不是一个有用的考虑点。诸如HashSet
、List
和Dictionary
之类的东西实际上会崩溃,因为数组不允许那么大,而且它们都由一个大数组支持。
@Svisstack "如果我们想在这个世界上那样,将一个项目放入哈希集中,您将拥有相同的包含时间,就像您将最大随机项目放入同一个哈希集中一样。"是的。 这是绝对正确的,假设该项目具有明确定义的散列函数。这就是哈希集如此有用的原因。检查一个项目是否在集合中需要大约相同的时间,而不管集合中有多少项目。它对您何时可以执行此操作有限制(该项目需要有效地进行哈希处理),但这是通常可以实现的条件。【参考方案3】:
如果您不需要排序,则不应使用进行排序的类,因为这意味着您的应用程序将完成比它需要的更多的工作。 (换句话说,这将使您的应用程序更快)。
【讨论】:
更重要的是,算法会跑得更快。散列是 O(1),而排序集可能使用二叉搜索树,在平均情况下是 O(log n) - 性能要差得多。 Set 用于唯一项目,List 可能包含重复条目。 msdn.microsoft.com/en-us/library/bb359438.aspx 用于 HashSetO(1)
中运行的算法意味着无论输入的大小如何,它都在相同的时间内运行。否则,时间取决于输入n
的大小,并表示为n
的函数。例如,线性的:O(n)
,二次的:O(n^2)
等。big-O wiki 页面可能很难阅读,this 总结得很好。
@BlueMonkMN,与您的旧错误版本相比,在线版本 (MSDN) 显然已修复。 SortedSet<>
在 O(log n) 时间内执行查找,HashSet<>
在 O(1) 时间内执行查找,List<>
在 O(n) 时间内执行。以上是关于SortedSet<T> 与 HashSet<T>的主要内容,如果未能解决你的问题,请参考以下文章
春眠不觉晓,Redis数据类型知多少?String,List,Set,SortedSet,Hash,Bitmap,HyperLogLogs