为什么SortedList <tkey,tvalue =“”>不使用指针值?</tkey,>

时间:2014-02-12 14:39:35

标签: c# .net data-structures

所以我正在查看SortedList<TKey, TValue>的实施情况以及Add的实施情况(下面显示的调用Insert真的让我感到惊讶。

Add方法执行明显的二进制搜索以确定KVP应该转到的索引,但Insert 似乎就好像可以改进显着(当然,虽然规模较大):

private void Insert(int index, TKey key, TValue value)
{
  if (this._size == this.keys.Length)
    this.EnsureCapacity(this._size + 1);
  if (index < this._size)
  {
    Array.Copy((Array) this.keys, index, (Array) this.keys, index + 1, this._size - index);
    Array.Copy((Array) this.values, index, (Array) this.values, index + 1, this._size - index);
  }
  this.keys[index] = key;
  this.values[index] = value;
  ++this._size;
  ++this.version;
}

如果我正确阅读此内容,并且我保留始终出错的权利,则此操作为O(2n)

在我看来,应该用指针实现。 一样LinkedList与密钥的值相关,但不是链接,因为它不支持随机访问。更多是只是链接到它的值。 get 操作不会慢,而且删除也不会因为我们有指针,但 add 操作现在会改为O(n)。< / p>

有人可以说明为什么这个决定可能会朝着这个方向发展吗?

2 个答案:

答案 0 :(得分:10)

这不应该让您感到惊讶,它在SortdList的MSDN文章中有详细记载:

  

SortedDictionary对未排序数据的插入和删除操作更快,O(logn)而不是SortedList的O(n)。

SortedDictionary使用红黑树(即“指针”),SortedList是一个数组。您可以根据对集合的处理方式在两者之间进行选择。两者都是用于查找的O(logn),但是如果你经常迭代这个集合,那么你可以在SortedList上取得很大进展。它更有效地使用cpu缓存。在现代机器上产生巨大的变化。

另请注意,向集合添加项目的效率在很大程度上取决于项目的排序方式。一个SortedDictionary 真的喜欢随机数据,给它更好的几率,不必重新平衡树。对它进行排序会给出最坏情况下的O(n)行为。 SortedList 真的喜欢排序的项目,使得添加O(1)。

答案 1 :(得分:1)

除了速度/大O复杂度之外的另一个非常重要的区别是内存开销。使用树(SortedDictionary),每个键/值对的开销大小为50-70字节(大约在F#的AVL树上测量,x64上有1M <int64,int64>项,但红色/黑色应该在该范围内),而SortedList每对只需要2个字节。

关键是,对于价值类型,例如<int,int>,SortedDictionary可以“浪费”多倍的内存而不是有用的有效负载,具有更快的随机插入的单一隔离优势。实际上,SortedList中CPU缓存的优势非常明显(O(lon n)查找中的常量),应该测量每个特定用例的差异(查找/插入的比率,插入模式,内存/速度要求)