. net有很多复杂的数据结构。不幸的是,其中一些非常相似,我不总是确定什么时候使用一个,什么时候使用另一个。我的大多数c#和VB书籍都在一定程度上讨论了它们,但它们从来没有真正深入任何细节。

数组、数组列表、列表、哈希表、字典、排序列表和排序字典之间的区别是什么?

哪些是可枚举的(IList -可以做'foreach'循环)?哪些使用键/值对(IDict)?

内存占用呢?插入速度?检索速度?

还有其他值得一提的数据结构吗?

我还在寻找内存使用和速度的更多细节(大o符号)


如果可能的话,使用泛型。这包括:

List而不是ArrayList 字典而不是哈希表


它们在智能感知上拼得很好。只需输入System.Collections。或者System.Collections.Generics(首选),你会得到一个可用的列表和简短描述。


首先,. net中的所有集合都实现了IEnumerable。

其次,很多集合是重复的,因为泛型是在框架的2.0版本中添加的。

因此,尽管泛型集合可能会添加功能,但在大多数情况下:

List是ArrayList的通用实现。 Dictionary<T,K>是Hashtable的泛型实现

数组是一个固定大小的集合,您可以更改存储在给定索引中的值。

SortedDictionary是一个<T,K>的字典,它基于键进行排序。 SortedList是一个<T,K>的字典,它基于所需的IComparer进行排序。

因此,字典实现(那些支持KeyValuePairs)是:

哈希表 词典<T,F> 排序列表<T,F> SortedDictionary<T,K>

. net 3.5中添加的另一个集合是Hashset。它是一个支持集合操作的集合。

而且,LinkedList是一个标准的链表实现(List是一个用于更快检索的数组列表)。


我能想到的是:

Array* - represents an old-school memory array - kind of like a alias for a normal type[] array. Can enumerate. Can't grow automatically. I would assume very fast insert and retrival speed. ArrayList - automatically growing array. Adds more overhead. Can enum., probably slower than a normal array but still pretty fast. These are used a lot in .NET List - one of my favs - can be used with generics, so you can have a strongly typed array, e.g. List<string>. Other than that, acts very much like ArrayList Hashtable - plain old hashtable. O(1) to O(n) worst case. Can enumerate the value and keys properties, and do key/val pairs Dictionary - same as above only strongly typed via generics, such as Dictionary<string, string> SortedList - a sorted generic list. Slowed on insertion since it has to figure out where to put things. Can enum., probably the same on retrieval since it doesn't have to resort, but deletion will be slower than a plain old list.

我倾向于一直使用List和Dictionary——一旦开始使用带有泛型的强类型,就很难再回到标准的非泛型了。

还有很多其他的数据结构,比如KeyValuePair,你可以用它做一些有趣的事情,还有SortedDictionary,它也很有用。


下面是给你的一些建议:

You can use foreach on types that implement IEnumerable. IList is essentially an IEnumberable with Count and Item (accessing items using a zero-based index) properties. IDictionary on the other hand means you can access items by any-hashable index. Array, ArrayList and List all implement IList. Dictionary, SortedDictionary, and Hashtable implement IDictionary. If you are using .NET 2.0 or higher, it is recommended that you use generic counterparts of mentioned types. For time and space complexity of various operations on these types, you should consult their documentation. .NET data structures are in System.Collections namespace. There are type libraries such as PowerCollections which offer additional data structures. To get a thorough understanding of data structures, consult resources such as CLRS.


哈希表/字典是O(1)性能,这意味着性能不是大小的函数。知道这一点很重要。

编辑:在实践中,哈希表/字典<>查找的平均时间复杂度是O(1)。


泛型集合和非泛型集合之间存在微妙和不那么微妙的差异。它们只是使用了不同的底层数据结构。例如,Hashtable保证了一个写入器-多个读取器而不需要同步。字典没有。


泛型集合将比非泛型集合执行得更好,特别是在遍历许多项时。这是因为装箱和开箱不再发生。


关于高频系统交易工程的哈希表与字典的一个重要注意事项:线程安全问题

Hashtable是线程安全的,可以被多个线程使用。 字典公共静态成员是线程安全的,但任何实例成员都不能保证是线程安全的。

因此,Hashtable仍然是这方面的“标准”选择。


我同情这个问题——我也发现(发现?)这个选择令人困惑,所以我开始科学地看看哪个数据结构是最快的(我用VB做了测试,但我想c#会是一样的,因为这两种语言在CLR级别上做同样的事情)。您可以在这里看到我进行的一些基准测试结果(还有一些关于在哪种情况下使用哪种数据类型最好的讨论)。


.NET数据结构:

接下来是关于为什么数组列表和列表是不同的

数组

正如一个用户所说,数组是“老派”的集合(是的,数组被认为是一个集合,尽管不是System.Collections的一部分)。但是,与其他集合相比,什么是“老派”的数组,即你在标题中列出的那些(这里,ArrayList和List(Of T))?让我们从基本的数组开始。

首先,Microsoft . net中的数组是“允许您将几个[逻辑相关的]项视为单个集合的机制”(参见链接文章)。这是什么意思?数组按顺序存储单个成员(元素),在内存中一个接一个地存储一个起始地址。通过使用数组,我们可以很容易地访问从该地址开始按顺序存储的元素。

除此之外,与编程101个常见概念相反,数组确实可以相当复杂:

Arrays can be single dimension, multidimensional, or jadded (jagged arrays are worth reading about). Arrays themselves are not dynamic: once initialized, an array of n size reserves enough space to hold n number of objects. The number of elements in the array cannot grow or shrink. Dim _array As Int32() = New Int32(100) reserves enough space on the memory block for the array to contain 100 Int32 primitive type objects (in this case, the array is initialized to contain 0s). The address of this block is returned to _array.

According to the article, Common Language Specification (CLS) requires that all arrays be zero-based. Arrays in .NET support non-zero-based arrays; however, this is less common. As a result of the "common-ness" of zero-based arrays, Microsoft has spent a lot of time optimizing their performance; therefore, single dimension, zero-based (SZs) arrays are "special" - and really the best implementation of an array (as opposed to multidimensional, etc.) - because SZs have specific intermediary language instructions for manipulating them.

数组总是通过引用(作为内存地址)传递——这是数组谜题的一个重要部分。当它们执行边界检查(将抛出错误)时,也可以在数组上禁用边界检查。

同样,数组的最大障碍是它们不能重新调整大小。他们有一个“固定的”容量。将数组列表和List(Of T)引入我们的历史:

ArrayList -非泛型列表

ArrayList(连同List(Of T)——尽管有一些关键的区别,在这里,后面会解释)——可能最好被认为是集合的下一个补充(在广义上)。从IList ('ICollection'的后代)接口继承的数组列表。数组列表本身比列表更庞大——需要更多的开销。

IList允许实现将数组列表视为固定大小的列表(如Arrays);然而,除了arraylist添加的额外功能之外,使用固定大小的arraylist并没有真正的优势,因为在这种情况下,arraylist(而不是Arrays)明显更慢。

从我的阅读中,数组列表不能是锯齿状的:“使用多维数组作为元素……不支持”。这是数组列表棺材上的又一颗钉子。数组列表也不是“类型化的”——这意味着,在所有东西的底层,一个数组列表只是一个动态的对象数组:Object[]。在实现arraylist时,这需要大量的装箱(隐式)和拆箱(显式),这又增加了它们的开销。

未经证实的想法:我记得我读过或听过我的一位教授说,数组列表有点像从数组到列表类型集合的尝试的私生子概念,也就是说,虽然曾经是数组的巨大改进,但随着对集合的进一步发展,它们不再是最好的选择

List(Of T): ArrayList变成了什么(以及希望变成什么)

The difference in memory usage is significant enough to where a List(Of Int32) consumed 56% less memory than an ArrayList containing the same primitive type (8 MB vs. 19 MB in the above gentleman's linked demonstration: again, linked here) - though this is a result compounded by the 64-bit machine. This difference really demonstrates two things: first (1), a boxed Int32-type "object" (ArrayList) is much bigger than a pure Int32 primitive type (List); second (2), the difference is exponential as a result of the inner-workings of a 64-bit machine.

那么,它和List(Of T)有什么区别呢?MSDN将List(Of T)定义为“…可以通过索引访问的强类型对象列表。”这里的重要性在于“强类型”部分:“识别”类型并将对象存储为其类型。因此,Int32类型存储为Int32类型,而不是Object类型。这消除了装箱和开箱引起的问题。

MSDN指定这种区别只在存储基元类型而不是引用类型时起作用。而且,这种差异确实存在于一个大范围:超过500个元素。更有趣的是,MSDN文档中写道:“使用List(of T)类的特定类型实现而不是使用ArrayList类....对您是有好处的。”

本质上,List(Of T)是ArrayList,但更好。它是ArrayList的“通用等效”。像ArrayList一样,它在被排序之前不能保证被排序(去想象)。List(Of T)还增加了一些功能。


我发现微软文档集合和数据结构页面上的“选择一个集合”部分非常有用

c#集合和数据结构:选择一个集合

还有下面的矩阵来比较一些其他的特征