C#集合类型大揭秘(4)

SortedList<TKEY,TVALUE>SortedDictionary<TKEY,TVALUE>同时支持快速查询和排序,SortedList<TKEY,TVALUE> 优势在于使用的内存比 SortedDictionary<TKEY,TVALUE> 少;但是SortedDictionary<TKEY,TVALUE>可对未排序的数据执行更快的插入和移除操作:它的时间复杂度为 O(log n),而 SortedList<TKEY,TVALUE> 为 O(n)。所以SortedList<TKEY,TVALUE>适用于既需要快速查找又需要顺序排列但是添加和删除元素较少的场景。

内部实现结构:

mark

根据Key获取Value的实现:

mark

IndexOfKey实现:

mark

添加新元素:

mark

添加操作:

mark

非关联性泛型集合类 1.List

泛型的List 类提供了不限制长度的集合类型,List内部实现使用数据结构是数组。我们都知道数组是长度固定的,那么List不限制长度必定需要维护这个数组。实际上List维护了一定长度的数组(默认为4),当插入元素的个数超过4或初始长度时,会去重新创建一个新的数组,这个新数组的长度是初始长度的2倍,然后将原来的数组赋值到新的数组中。

我们可以通过ILSpy看一下List源码证明我们上面所说的:

List内部重要变量:

mark

mark

新增元素操作:

mark

新增元素确认数组容量:

mark

真正的数组扩容操作:

mark

数组扩容的场景涉及到对象的创建和赋值,是比较消耗性能的。所以如果能指定一个合适的初始长度,能避免频繁的对象创建和赋值。再者,因为内部的数据结构是数组,插入和删除操作需要移动元素位置,所以不适合频繁的进行插入和删除操作;但是可以通过数组下标查找元素。所以List适合读多写少的场景。

2.LinkedList

上面我们提到List适合读多写少的场景,那么必定有一个List适合写多读少的场景,就是这货了——LinkedList。至于为什么适合写多读少,熟悉数据结构的同学应该已经猜到了。因为LinkedList的内部实现使用的是链表结构,而且还是双向链表。直接看源码:

mark

因为内部实现结构是链表,所以可以在某一个节点前或节点后插入新的元素。

链表节点定义:

mark

我们以在某个节点前插入新元素为例:

mark

具体的插入操作,注意操作步骤不能颠倒:

mark

3.HashSet

HashSet是一个无序的能够保持唯一性的集合。我们可以将HashSet看作是简化的Dictionary<TKEY,TVALUE>,只不过Dictionary<TKEY,TVALUE>存储的键值对对象,而HashSet存储的是普通对象。其内部实现也和Dictionary<TKEY,TVALUE>基本一致,也是散列函数加双数组实现的,区别是存储的Slot结构体不再有key。

内部实现数据结构:

m_slots中所存放的是Slot结构体,Slot结构体由3个部分组成,如下所示:

mark

添加新元素的具体实现:

Dictionary<TKEY,TVALUE>添加新元素的实现基本一致。

mark

4.SortedSet

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ffbb9b0749e1e76a7b6d186e7cb0a321.html