【问题标题】:Why are sorted dictionaries and lists slower to add, delete, and get values than unsorted?为什么排序字典和列表的添加、删除和获取值比未排序的要慢?
【发布时间】:2012-11-28 21:34:39
【问题描述】:

我做了一些测试:SortedDictionary、SortedList 和 Dictionary(只是为了比较)。结果是 Dictionary 在基于键的添加、删除和返回值方面比其他两个快得多(每个字典中有 100,000 对键+值)。

谁能告诉我为什么 SortedList 和 SortedDictionary 比 Dictionary 慢?

【问题讨论】:

  • 因为正如名称所暗示的那样,每次将项目添加到集合中时,都会对它们进行排序。

标签: c# testing dictionary sortedlist sorteddictionary


【解决方案1】:

以基于未排序列表的排序列表为例。

让我们假设在任意索引处的未排序列表上的插入时间为 O(n/2),其中 n 是列表的大小。这反映了平均而言,必须移动一半的列表元素才能为插入的元素腾出空间。

同样,在这个列表中,从任意位置移除一个元素也是 O(n/2),因为平均而言,必须移动一半的元素来缩小差距。

。 . .

现在,想象一下同样的实现,但有排序。

排序必须在插入时完成——它必​​须找到新元素的位置。由于之前的所有元素都已经排序(我们在插入时这样做,所以这是真的),我们可以从头开始扫描。

这是一个 O(n/2) 操作,甚至在我们开始插入之前。那只是为了找到插入点。

一种更好的方法,使用二分搜索可以让我们 O(log n) 找到插入位置,但仍然在支付 O(n/2) 成本之前进行插入本身。

如果一个扫描操作的代价是s,插入操作的代价是m(对于移动),那么排序插入的代价是:

s x O(log n) + m x (n/2)

但是,对未排序列表任意位置的插入操作只是:

 m x (n /2)

这是排序操作需要更长时间的真正原因的具体示例。

这种类型的理论还有很多,但这应该是一个开始。

【讨论】:

  • 以上描述中的所有日志引用都是base 2,记录一下。
  • 添加/删除到 SortedDictionary(与您正确分析的 SortedList 相反)将是 O(log(n)) 而不是 O(n)。
  • @Servy 我选择了一个更简单的例子,主要是因为我不知道 C# 的 Dictionary 排序字典类型对象的底层实现,并且因为我已经 20 年没有做过这种类型的分析了并且不想因为记错东西而显得太愚蠢!
  • Dictionary 被实现为一个 has 表。 SortedDictionary 是一棵红/黑树。 SortedList 是……好吧,你分析得对。它也是迄今为止三个中最没用的。迄今为止,我从未发现值得使用的情况。我一直使用Dictionary对象(即通常每天,或接近它)。 SortedDictionary 我(个人)使用的频率要低得多,但它确实有一席之地。
【解决方案2】:

因为这些数据结构在每次添加或删除值时都会进行一次排序再次。因此,您在使用它们时会受到性能影响。

【讨论】:

  • 不完全。一些蛮力的幼稚实现可能每次都进行完整排序,但更好的实现不会。但是,无论底层实现是什么,都必须努力维护排序不变性。
  • 另外remove可能不需要内部重组。
  • 好的,所以添加和删除你一定是对的,排序会变慢,但是为什么我的返回值也不好(键和值是字符串)?
  • @Berserker 我不知道你上一条评论中的问题是什么意思。
  • @Berserker 这是因为您正在进行二进制搜索,即 O(log(n)) 而不是仅对值进行散列,即 O(1)。
【解决方案3】:

字典只是将新条目扔到列表的末尾。它所要做的就是跟踪列表末尾的位置。但是,SortedDictionary 必须在列表中找到正确的位置来放置新条目。显然,这需要一些计算工作,并且会比简单地添加到末尾要慢。

对于删除,这两种类型的对象都必须找出要删除的记录,但排序类型需要评估删除该记录对其内部结构的影响。例如,一个 b-tree 可能需要在删除后重新平衡它的分支。同样需要一些计算来评估这一点。因此性能上的差异。

【讨论】:

  • A Dictionary 不会添加到末尾,它会计算键的哈希值,然后将值添加到该哈希值存储桶的索引中。它可以在恒定时间内做到这一点(如果哈希冲突率较低)。 SortedDictionary 需要进行二进制搜索以找到适当的添加/删除位置(即 O(log(n)) 时间,但可以在 O(1) 时间内进行实际添加/删除(假设树是平衡的, 如果它是一棵红/黑树).SortedList 只是一个不好使用的数据结构;添加/删除时需要向上/向下移动一堆元素,所以不要使用它.
  • 你说得对。我写了字典,但脑子里有列表。你的额外细节很棒。
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 2017-03-11
  • 2018-06-03
  • 2011-09-17
  • 2021-09-02
相关资源
最近更新 更多