SortedList和SortedDictionary有什么区别?

时间:2009-06-01 16:35:46

标签: c# .net generics sortedlist sorteddictionary

SortedList<TKey,TValue>SortedDictionary<TKey,TValue>之间是否存在实际差异?在任何情况下你都会专门使用一个而不是另一个吗?

7 个答案:

答案 0 :(得分:280)

是的 - 他们的表现特征差别很大。将它们称为SortedListSortedTree可能会更好,因为这更能反映实施情况。

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

  

SortedDictionary<TKey, TValue>通用   class是二叉搜索树   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>

  •   

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

答案 1 :(得分:96)

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

效果角度来看:

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

您可以阅读更多hereherehereherehere

答案 2 :(得分:21)

我破解了开放的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++;
}

答案 3 :(得分:13)

查看MSDN page for 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>)>)对未排序数据O(log n)提供了更快的插入和删除操作,而O(n)则为SortedList<(Of <(TKey, TValue>)>)

  •   
  • 如果列表是从排序数据中一次性填充的,则SortedList<(Of <(TKey, TValue>)>)SortedDictionary<(Of <(TKey, TValue>)>)快。

  •   

答案 4 :(得分:11)

这是表演相互比较的直观表现。

答案 5 :(得分:7)

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

-

时应使用

排序字典

  • 需要更多插入和删除操作。
  • 未订购的数据。
  • 密钥访问就足够了,不需要索引访问。
  • 记忆不是瓶颈。

另一方面, -

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

希望这会有所帮助!!

答案 6 :(得分:0)

索引访问(这里提到)是实际的区别。 如果需要访问后继者或前任者,则需要SortedList。 SortedDictionary无法做到这一点,因此您对使用排序(第一个/ foreach)的方式相当有限。

相关问题