SortedList<&gt ;,SortedDictionary<>和词典<>

时间:2009-09-15 13:21:20

标签: c# generics dictionary sortedlist sorteddictionary

我发现SortedList<TKey, TValue> SortedDictionary<TKey, TValue>Dictionary<TKey, TValue>实现了相同的接口。

  1. 我们应该何时选择SortedListSortedDictionary而不是Dictionary
  2. 在申请方面SortedListSortedDictionary之间有什么区别?

6 个答案:

答案 0 :(得分:84)

  1. 当迭代两者中的任何一个元素时,元素将被排序。 Dictionary<T,V>不是这样。

  2. MSDN解决了SortedList<T,V>SortedDictionary<T,V>之间的区别:

  3.   

    SortedDictionary(TKey,TValue)泛型类是binary search tree,带有O(log n)检索,其中n是元素的数量   词典。在这方面,它类似于SortedList(TKey,   TValue)泛类。这两个类具有相似的对象模型,并且   两者都有O(log n)检索。两个班级不同的地方是   记忆的使用和插入和移除的速度:

         

    SortedList(TKey,TValue)使用的内存少于SortedDictionary(TKey,   TValue)。

         

    SortedDictionary(TKey,TValue)具有更快的插入和删除功能   未排序数据的操作:O(log n)而不是O(n)   SortedList(TKey,TValue)。

         

    如果列表是从排序数据中一次性填充的,   SortedList(TKey,TValue)比SortedDictionary(TKey,   TValue)。

答案 1 :(得分:57)

enter image description here

我会提到字典之间的区别。

上图显示Dictionary<K,V>在每种情况下均等于或快于Sorted模拟,但如果需要元素顺序,例如要打印它们,Sorted选择一个。

Src:http://people.cs.aau.dk/~normark/oop-csharp/html/notes/collections-note-time-complexity-dictionaries.html

答案 2 :(得分:19)

总结Performance Test - SortedList vs. SortedDictionary vs. Dictionary vs. Hashtable的结果,不同情景的结果从最好到最差:

内存使用:

SortedList<T,T>
Hashtable
SortedDictionary<T,T>
Dictionary<T,T>

<强>的插入

Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
SortedList<T,T>

搜索操作:

Hashtable
Dictionary<T,T>
SortedList<T,T>
SortedDictionary<T,T>

foreach循环操作

SortedList<T,T>
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>

答案 3 :(得分:8)

  1. 当您希望在迭代时按键对集合进行排序时。如果您不需要对数据进行排序,那么只需使用词典就可以获得更好的效果,它会有更好的表现。

  2. SortedList和SortedDictionary几乎做同样的事情,但实现方式不同,因此具有不同的优点和缺点explained here

答案 4 :(得分:2)

我可以看到建议的答案集中在性能上。下面提供的文章未提供有关性能的任何新信息,但说明了其基本机制。还要注意,它不关注问题中提到的三个Collection类型,而是解决了System.Collections.Generic名称空间的所有类型。

http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

提取物:

字典<>

  

字典可能是最常用的关联容器类。字典是用于关联查找/插入/删除的最快的类,因为它在封面下使用哈希表。因为键是散列的,所以键类型应正确地正确实现GetHashCode()和Equals(),或者在构造时应为字典提供外部IEqualityComparer。字典中项目的插入/删除/查找时间是摊销的恒定时间-O(1)-这意味着,不管字典有多大,找到某物所花费的时间都保持相对恒定。这对于高速查找是非常理想的。唯一的缺点是,由于使用哈希表的性质,字典是无序的,因此您无法轻松地依次遍历字典中的项目

SortedDictionary <>

  

SortedDictionary在用法上类似于Dictionary,但在实现上有很大不同。 SortedDictionary在封面下使用一棵二叉树来按键对项目进行维护。作为排序的结果,用于密钥的类型必须正确实现IComparable ,以便可以正确地对密钥进行排序。排序后的字典需要一些查找时间,以维护项目的顺序,因此排序字典中的插入/删除/查找时间是对数-O(log n)。一般而言,使用对数时间,您可以将集合的大小增加一倍,并且只需执行一次额外的比较即可找到该项目。如果您想快速查找但又希望能够通过键维护集合,请使用SortedDictionary。

SortedList <>

  

SortedList是通用容器中的另一个已排序的关联容器类。再一次像SortedDictionary一样,SortedList,使用键对键值对进行排序。但是,与SortedDictionary不同, SortedList中的项目存储为项目的排序数组。这意味着插入和删除是线性的-O(n)-因为删除或添加项目可能涉及将列表中的所有项目上移或下移。但是,查找时间为O(log n),因为SortedList可以使用二进制搜索通过其键在列表中找到任何项目。那么,为什么要这么做呢?好吧,答案是,如果您要预先加载SortedList,则插入速度会较慢,但是由于数组索引比跟随对象链接快,因此查找要比SortedDictionary快一点。再一次在需要快速查找并希望按键顺序维护集合并且很少有插入和删除操作的情况下使用此方法。


基本程序的初步摘要

非常欢迎您提供反馈,因为我确定我做得不好。

  • 所有数组的大小为n
  • 未排序的数组= .Add / .Remove为O(1),但.Item(i)为O(n)。
  • 排序数组= .Add / .Remove为O(n),但是 .Item(i)是O(1)。

词典

内存

KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>

添加

  1. 添加HashArray(n) = Key.GetHash#O(1)
  2. 添加KeyArray(n) = PointerToKey#O(1)
  3. 添加ItemArray(n) = PointerToItem#O(1)

删除

  1. For i = 0 to n,找到i,其中HashArray(i) = Key.GetHash#O(log n)(排序数组)
  2. 删除HashArray(i)#O(n)(排序数组)
  3. 删除KeyArray(i)#O(1)
  4. 删除ItemArray(i)#O(1)

获取物品

  1. For i = 0 to n,找到i,其中HashArray(i) = Key.GetHash#O(log n)(排序数组)
  2. 返回ItemArray(i)

遍历

  1. For i = 0 to n,返回ItemArray(i)

排序字典

内存

KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>

添加

  1. 添加KeyArray(n) = PointerToKey#O(1)
  2. 添加ItemArray(n) = PointerToItem#O(1)
  3. For i = 0 to n,找到i,其中KeyArray(i-1) < Key < KeyArray(i)(使用ICompare)#O(n)
  4. 添加OrderArray(i) = n#O(n)(排序数组)

删除

  1. For i = 0 to n,找到i,其中KeyArray(i).GetHash = Key.GetHash#O(n)
  2. 删除KeyArray(SortArray(i))#O(1)
  3. 删除ItemArray(SortArray(i))#O(1)
  4. 删除OrderArray(i)#O(n)(排序数组)

获取物品

  1. For i = 0 to n,找到i,其中KeyArray(i).GetHash = Key.GetHash#O(n)
  2. 返回ItemArray(i)

遍历

  1. For i = 0 to n,返回ItemArray(OrderArray(i))

排序列表

内存

KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>

添加

  1. For i = 0 to n,找到i,其中KeyArray(i-1) < Key < KeyArray(i)(使用ICompare)#O(log n)
  2. 添加KeyArray(i) = PointerToKey#O(n)
  3. 添加ItemArray(i) = PointerToItem#O(n)

删除

  1. For i = 0 to n,找到i,其中KeyArray(i).GetHash = Key.GetHash#O(log n)
  2. 删除KeyArray(i)#O(n)
  3. 删除ItemArray(i)#O(n)

获取物品

  1. For i = 0 to n,找到i,其中KeyArray(i).GetHash = Key.GetHash#O(log n)
  2. 返回ItemArray(i)

遍历

  1. For i = 0 to n,返回ItemArray(i)

答案 5 :(得分:0)

尝试为@Lev提出的每种情况分配性能得分,我使用了以下值:

  • O(1)= 3
  • O(log n)= 2
  • O(n)= 1
  • O(1)或O(n)= 2
  • O(log n)或O(n)= 1.5

结果是(越高=越好):

Dictionary:       12.0 
SortedDictionary:  9.0 
SortedList:        6.5

当然,每个用例都会为某些操作赋予更多权重。