SortedList和SortedDictionary有什么区别?


261

a SortedList<TKey,TValue>和a 之间有什么实际的实际区别SortedDictionary<TKey,TValue>吗?在任何情况下,您会专门使用一种而不是另一种吗?



13
我很困惑。为什么SortedList具有两个类型参数SortedList<TKey,TValue>而不是一个SortedList<T>?为什么不执行IList<T>呢?
上校恐慌

3
@ColonelPanic,因为在功能上SortedList是地图,而不是线性集合。不要让这个名字愚弄你。就像字典一样,您输入密钥,就可以返回值。当字典是无序的时,SortedList会以其自然排序的顺序进行排序。
nawfal

Answers:


294

是的-它们的性能特征差异很大。最好打电话给他们SortedListSortedTree为更紧密地体现了落实。

查看其中每个()的MSDN文档SortedListSortedDictionary以了解不同情况下不同操作的性能细节。这是一个不错的摘要(来自SortedDictionary文档):

SortedDictionary<TKey, TValue>通用类是O(log n)的检索,其中n是字典中的元件的数目的二进制搜索树。在这方面,它类似于 SortedList<TKey, TValue>泛型类。这两个类具有相似的对象模型,并且都具有O(log n)检索。这两类的区别在于内存使用以及插入和移除的速度:

  • SortedList<TKey, TValue>使用的记忆体少于SortedDictionary<TKey, TValue>

  • SortedDictionary<TKey, TValue>对未排序的数据O(log n)具有更快的插入和删除操作,而对O的O(n)具有更快的插入和删除操作 SortedList<TKey, TValue>

  • 如果从排序数据中一次填充列表,SortedList<TKey, TValue>则速度比快 SortedDictionary<TKey, TValue>

SortedList实际上是维护一个排序的数组,而不是使用树。它仍然使用二进制搜索来查找元素。)


非常感谢所有的指针。我想我对RTFM太懒了……在SO上向好人问……要容易得多;)我投票给你们两个,以寻求答案。乔恩(Jon)因抢先触发而获得了答案。:)
Shaul Behr

2
我认为应该更正SortedList定义,因为我不认为它是二进制搜索树...?
nchaud

1
我使用了反射器,发现它没有使用二进制搜索树。
Daniel Imms

我认为Sorteddictionary是AVL树或Red-Blacktree(所有操作成本为O(logn)。而SortedList是二进制搜索(在最坏的情况下,它花费o(n)时间))
Ghoster

105

这是一个表格视图,如果有帮助...

性能角度来看:

+------------------+---------+----------+--------+----------+----------+---------+
| Collection       | Indexed | Keyed    | Value  | Addition |  Removal | Memory  |
|                  | lookup  | lookup   | lookup |          |          |         |
+------------------+---------+----------+--------+----------+----------+---------+
| SortedList       | O(1)    | O(log n) | O(n)   | O(n)*    | O(n)     | Lesser  |
| SortedDictionary | n/a     | O(log n) | O(n)   | O(log n) | O(log n) | Greater |
+------------------+---------+----------+--------+----------+----------+---------+

* Insertion is O(1) for data that are already in sort order, so that each 
  element is added to the end of the list (assuming no resize is required).

实现的角度来看:

+------------+---------------+----------+------------+------------+------------------+
| Underlying | Lookup        | Ordering | Contiguous | Data       | Exposes Key &    |
| structure  | strategy      |          | storage    | access     | Value collection |
+------------+---------------+----------+------------+------------+------------------+
| 2 arrays   | Binary search | Sorted   | Yes        | Key, Index | Yes              |
| BST        | Binary search | Sorted   | No         | Key        | Yes              |
+------------+---------------+----------+------------+------------+------------------+

大致复述,如果您需要原始性能SortedDictionary可能是一个更好的选择。如果您需要较少的内存开销,则索引检索SortedList更适合。有关何时使用哪个的更多信息,请参见此问题。

您可以在这里这里这里这里这里阅读更多。


请注意,如果要获得良好的性能较低的内存使用量索引检索,请考虑BDictionary<Key,Value>使用LoycCore而不是SortedDictionary
Qwertie

1
是的,请看本文的底部。事实证明BDictionary,通常它比SortedDictionary非常大的尺寸要慢,但是比SortedList有700多个项目时要快。由于在树的叶子中使用了数组,因此内存使用量应仅略高于SortedList(远低于SortedDictionary)。
Qwertie

22

我破解了Reflector来看看这个,因为似乎有些困惑SortedList。实际上,不是二叉搜索树,而是键-值对的排序数组(按键)。还有一个TKey[] keys与键值对同步排序变量,用于二进制搜索。

这是一些资料(针对.NET 4.5)来备份我的主张。

私人会员

// Fields
private const int _defaultCapacity = 4;
private int _size;
[NonSerialized]
private object _syncRoot;
private IComparer<TKey> comparer;
private static TKey[] emptyKeys;
private static TValue[] emptyValues;
private KeyList<TKey, TValue> keyList;
private TKey[] keys;
private const int MaxArrayLength = 0x7fefffff;
private ValueList<TKey, TValue> valueList;
private TValue[] values;
private int version;

SortedList.ctor(IDictionary,IComparer)

public SortedList(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer) : this((dictionary != null) ? dictionary.Count : 0, comparer)
{
    if (dictionary == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
    }
    dictionary.Keys.CopyTo(this.keys, 0);
    dictionary.Values.CopyTo(this.values, 0);
    Array.Sort<TKey, TValue>(this.keys, this.values, comparer);
    this._size = dictionary.Count;
}

SortedList.Add(TKey,TValue):空

public void Add(TKey key, TValue value)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    int num = Array.BinarySearch<TKey>(this.keys, 0, this._size, key, this.comparer);
    if (num >= 0)
    {
        ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
    }
    this.Insert(~num, key, value);
}

SortedList.RemoveAt(int):无效

public void RemoveAt(int index)
{
    if ((index < 0) || (index >= this._size))
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
    }
    this._size--;
    if (index < this._size)
    {
        Array.Copy(this.keys, index + 1, this.keys, index, this._size - index);
        Array.Copy(this.values, index + 1, this.values, index, this._size - index);
    }
    this.keys[this._size] = default(TKey);
    this.values[this._size] = default(TValue);
    this.version++;
}

13

MSDN页面的SortedList

从“备注”部分:

SortedList<(Of <(TKey, TValue>)>)泛型类是用二叉搜索树O(log n)的检索,其中n在字典中元素的个数。在这方面,它类似于SortedDictionary<(Of <(TKey, TValue>)>)泛型类。这两个类具有相似的对象模型,并且都具有O(log n)检索功能。这两类的区别在于内存使用以及插入和移除的速度:

  • SortedList<(Of <(TKey, TValue>)>)使用的记忆体少于SortedDictionary<(Of <(TKey, TValue>)>)
  • SortedDictionary<(Of <(TKey, TValue>)>)与for O(log n)相比,O(n)对未排序的数据具有更快的插入和删除操作SortedList<(Of <(TKey, TValue>)>)

  • 如果从排序数据中一次填充列表,SortedList<(Of <(TKey, TValue>)>)则速度比快SortedDictionary<(Of <(TKey, TValue>)>)


9
引用的文本是错误的(并且已在MSDN上更新):SortedList不是“二进制搜索树”,而是“键/值对数组”。
Eldritch难题,2012年

12

这是表现如何相互比较的直观表示。


您从哪里获取这些信息?从这个方案中我们可以看出,Dictinary在任何方面都更好,因此没有理由存在其他人。
亚历克斯·科斯汀

9

关于这个话题已经足够了,但是为了简单起见,这是我的观点。

排序字典应在以下情况下使用:

  • 需要更多的插入和删除操作。
  • 数据无序。
  • 密钥访问就足够了,不需要索引访问。
  • 内存不是瓶颈。

另一方面,在以下情况下应使用排序列表:

  • 需要更多的查找,更少的插入和删除操作。
  • 数据已经排序(如果不是全部,则为大多数)。
  • 需要索引访问。
  • 内存是一项开销。

希望这可以帮助!!


1

索引访问(此处提到)是实际的区别。如果需要访问后继或前任,则需要SortedList。SortedDictionary无法做到这一点,因此您在使用排序方式(优先/ foreach)方面受到了很大的限制。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.