SortedList 和 SortedDictionary 有啥区别?

Posted

技术标签:

【中文标题】SortedList 和 SortedDictionary 有啥区别?【英文标题】:What's the difference between SortedList and SortedDictionary?SortedList 和 SortedDictionary 有什么区别? 【发布时间】:2009-06-01 16:35:45 【问题描述】:

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

【问题讨论】:

相关:When to use a SortedList or a SortedDictionary 我很困惑。为什么SortedList 有两个类型参数SortedList<TKey,TValue> 而不是一个SortedList<T>?为什么不实现IList<T> @ColonelPanic 因为在功能上 SortedList 是一个映射,而不是一个线性集合。不要让这个名字欺骗你。就像字典一样,你传入一个键,你会得到一个值。虽然字典是无序的,但 SortedList 是按其自然排序顺序排序的。 【参考方案1】:

是的 - 它们的性能特征显着不同。将它们称为 SortedListSortedTree 可能会更好,因为这更能反映实现。

查看每个人的 MSDN 文档(SortedListSortedDictionary),了解不同情况下不同操作的性能详情。这是一个很好的总结(来自SortedDictionary 文档):

SortedDictionary<TKey, TValue> 泛型 类是一个二叉搜索树 O(log n) 检索,其中 n 是 字典中的元素数量。 在这方面,它类似于 SortedList<TKey, TValue> 通用 班级。两个班有相似之处 对象模型,并且都有 O(log n) 恢复。哪两个班 不同之处在于内存使用和速度 插入和移除:

SortedList&lt;TKey, TValue&gt; 使用较少 内存大于SortedDictionary<TKey, TValue>

SortedDictionary&lt;TKey, TValue&gt; 有 更快的插入和移除 未排序数据的操作,O(log n) 与 O(n) 相反 SortedList&lt;TKey, TValue&gt;

如果列表被一次性填充 从排序数据来看,SortedList<TKey, TValue>SortedDictionary&lt;TKey, TValue&gt;.

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

【讨论】:

非常感谢大家的指点。我想我对 RTFM 太懒了……更容易在 SO 上问好人……;)我投票给你们两个答案;乔恩因第一个触发而获得答案。 :) 我认为应该更正 SortedList 的定义,因为我不相信它是二叉搜索树...? 我用反射器看了看,发现它没有使用二叉搜索树。 我认为 Sorteddictionary 是 AVL-tree 或 Red-Blacktree(所有操作成本为 O(logn)。SortedList 是二进制搜索(在最坏的情况下花费 o(n) 时间)l【参考方案2】:

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

性能的角度来看:

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

  * Insertion is O(log n) for data that are already in sort order, so that each 
    element is added to the end of the list. If a resize is required, that element
    takes O(n) time, but inserting n elements is still amortized O(n log n).
    list.
** Available through enumeration, e.g. Enumerable.ElementAt.

实施的角度来看:

+------------+---------------+----------+------------+------------+------------------+
| 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 更适合。 See this question for more on when to use which.

您可以阅读更多here、here、here、here 和here。

【讨论】:

请注意,如果您想要良好的性能相对较低的内存使用量索引检索,请考虑使用BDictionary&lt;Key,Value&gt; in LoycCore 而不是SortedDictionary。跨度> 是的,看this article的底部。事实证明,BDictionary 通常比SortedDictionary 慢,除了非常大的尺寸,但如果有超过 700 个左右的项目,它比SortedList 快。由于在树的叶子中使用了数组,内存使用量应仅略高于SortedList(远低于SortedDictionary)。 不幸的是,有序插入到 SortedList 中每个元素是 O(log n)。在执行二分搜索之前只需一次检查就可以轻松实现 O(1)。【参考方案3】:

我打开 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) : void

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) : void

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++;

【讨论】:

【参考方案4】:

查看MSDN page for SortedList:

来自备注部分:

SortedList&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 泛型类是具有O(log n) 检索的二叉搜索树,其中n 是字典中的元素数。在这方面,它类似于SortedDictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 泛型类。这两个类具有相似的对象模型,并且都具有O(log n) 检索。这两个类的不同之处在于内存使用和插入和删除速度:

SortedList&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 使用的内存少于 SortedDictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;)

SortedDictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 对未排序的数据具有更快的插入和删除操作,O(log n)O(n)SortedList&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 相比。

如果列表是从排序数据中一次性填充的,SortedList&lt;(Of &lt;(TKey, TValue&gt;)&gt;)SortedDictionary&lt;(Of &lt;(TKey, TValue&gt;)&gt;) 快。

【讨论】:

引用的文字有误(在 MSDN 上已更新):SortedList 不是“二叉搜索树”,它是“键/值对数组”。【参考方案5】:

这是性能相互比较的直观表示。

【讨论】:

你从哪里得到的信息?从这个方案我们可以看出Dictinary在任何方面都更好,所以没有理由让其他人存在。 @alexkostin 可能有点晚,但请参阅***.com/a/19702706/7224691。我的源链接有问题,但我可以在回程机器上找到它。 @alexkostin Dictionary&lt;K, V&gt; 不保留其元素的插入顺序,其中SortedList&lt;K, V&gt;SortedDictionary&lt;K, V&gt; 按给定IComparer&lt;K&gt; 的顺序排列。【参考方案6】:

关于这个话题已经说得够多了,但为了简单起见,这是我的看法。

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

需要更多的插入和删除操作。 数据未排序。 键访问就够了,不需要索引访问。 内存不是瓶颈。

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

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

希望这会有所帮助!

【讨论】:

【参考方案7】:

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

【讨论】:

以上是关于SortedList 和 SortedDictionary 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

《C#零基础入门之百识百例》(八十九)SortedList和SortedDictionary介绍 --对比解析

为啥Java中没有SortedList?

c#的SortedList使用方法

SortedList的使用示例

为啥 .NET 中没有 SortedList<T>? [关闭]

如何遍历类中的 SortedList