SortedList和SortedDictionary有什么区别?

Sha*_*ica 251 .net c# generics sortedlist sorteddictionary

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

Jon*_*eet 287

是的 - 他们的表现特征差别很大.打电话给他们可能会更好SortedList,SortedTree因为这更能反映实施情况.

查看每个(SortedListSortedDictionary)的MSDN文档,了解不同情况下不同操作的性能详情.这是一个很好的总结(来自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(n) SortedList<TKey, TValue>.

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

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

  • 我认为SortedList定义应该更正,因为我不相信它是一个二叉搜索树...? (2认同)

naw*_*fal 98

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

绩效角度来看:

+------------------+---------+----------+--------+----------+----------+---------+
| 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).
Run Code Online (Sandbox Code Playgroud)

实施角度来看:

+------------+---------------+----------+------------+------------+------------------+
| 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              |
+------------+---------------+----------+------------+------------+------------------+
Run Code Online (Sandbox Code Playgroud)

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

您可以在这里,这里,这里,这里这里阅读更多内容.


Dan*_*mms 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;
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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++;
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*han 13

查看SortedListMSDN页面:

从备注部分:

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>)>).

  • 引用的文本是错误的(并在MSDN上更新):SortedList不是"二进制搜索树",它是"键/值对数组". (9认同)

Lev*_*Lev 12

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


Pra*_*thi 9

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

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

  • 需要更多插入和删除操作.
  • 数据未按顺序排列.
  • 密钥访问就足够了,不需要索引访问.
  • 记忆不是瓶颈.

另一方面,在以下情况下应使用分类清单

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

希望这可以帮助!!