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】:
是的 - 它们的性能特征显着不同。将它们称为 SortedList
和 SortedTree
可能会更好,因为这更能反映实现。
查看每个人的 MSDN 文档(SortedList
、SortedDictionary
),了解不同情况下不同操作的性能详情。这是一个很好的总结(来自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
实际上维护了一个排序数组,而不是使用树。它仍然使用二进制搜索来查找元素。)
【讨论】:
非常感谢大家的指点。我想我对 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<Key,Value>
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<(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 不是“二叉搜索树”,它是“键/值对数组”。【参考方案5】:这是性能相互比较的直观表示。
【讨论】:
你从哪里得到的信息?从这个方案我们可以看出Dictinary在任何方面都更好,所以没有理由让其他人存在。 @alexkostin 可能有点晚,但请参阅***.com/a/19702706/7224691。我的源链接有问题,但我可以在回程机器上找到它。 @alexkostinDictionary<K, V>
不保留其元素的插入顺序,其中SortedList<K, V>
和SortedDictionary<K, V>
按给定IComparer<K>
的顺序排列。【参考方案6】:
关于这个话题已经说得够多了,但为了简单起见,这是我的看法。
排序字典应该在以下情况下使用-
需要更多的插入和删除操作。 数据未排序。 键访问就够了,不需要索引访问。 内存不是瓶颈。另一方面,排序列表应该在以下情况下使用-
需要更多的查找和更少的插入和删除操作。 数据已经排序(如果不是全部,也是大部分)。 需要索引访问权限。 内存是一种开销。希望这会有所帮助!
【讨论】:
【参考方案7】:索引访问(这里提到)是实际的区别。 如果需要访问后继者或前驱者,则需要 SortedList。 SortedDictionary 无法做到这一点,因此您在使用排序方式(first / foreach)方面受到了相当大的限制。
【讨论】:
以上是关于SortedList 和 SortedDictionary 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
《C#零基础入门之百识百例》(八十九)SortedList和SortedDictionary介绍 --对比解析