【问题标题】:Suitable Collection class for Sorted Data requiring fast retrieval适合需要快速检索的排序数据的集合类
【发布时间】:2015-05-03 23:49:50
【问题描述】:

我在需要存储KeyValuePair 集合的场景中工作,其中DateTimeOffset 作为键。 我收到了这个数据的列表(通过 Http 请求),我只需要从中读取和生成集合。要求集合保持有序,并且必须是可枚举的。另外,我可能需要按键对这些数据进行大量查找。

还要注意,我收到的数据本身已经排序。我可能会定期重复接收数据并再次生成集合的操作。然而,现有的集合并没有被修改,而是每次我刷新数据时都会创建一个新的集合。

现在,我想到了这些方法:

  1. 使用SortedDictionary<,>(我目前的方法)。
  2. 使用Dictionary<,>,在从接收到的数据中填充所有项目后手动排序。 (虽然这使得查找速度非常快 (O(1)),但我现在需要对数据进行排序,因为 Dictionary<,> 在以有序方式添加时不会维护其项目。)
  3. 使用直接从数据中填充的简单数组(或List)。元素的顺序是隐式维护的。然后,使用对键的二分搜索来搜索项目(即查找)。

哪种方法适合这种情况?我可以使用上述方法的任何其他选项或变体来获得更好的整体性能吗?

编辑

对不起,我忘了提到我正在为 WinRT(特别是 Windows Phone)平台进行开发。因此我不能使用SortedList<,>(也不能使用OrderedDictionary),这将是@lc 指出的最佳选择。

另外,我的收藏只有几百件。也许在这个规模上可能没有任何显着差异,但我还是想知道一个答案。

【问题讨论】:

  • 假设存在一个数据结构可以满足您的需求。你能详细说明你想提出这个数据结构的问题的细节,以及你想要什么样的答案吗?例如,您是否需要通过索引访问它?您需要将其作为一个整体排序输出吗?是不是只在进场的时候整理的?如果你将一个用于索引+排序访问的列表和一个用于直接键查找的字典结合起来会怎样?
  • 快速查看 MSDN,SortedList<,> 实际上可能就是您所追求的。特别是看msdn.microsoft.com/en-us/library/ms132319%28v=vs.110%29.aspx的备注部分
  • 取决于您最常做的事情,您可以选择您的数据结构。如果您主要查找并且很少修改集合——您需要一个在查找中表现更好的集合。等等。 This may help
  • @Lasse 我需要将它作为一个整体输出。此外,它永远不会被操纵。刷新时,会准备新的集合并丢弃旧的集合。
  • @Ic 请查看问题的编辑,谢谢。

标签: c# collections


【解决方案1】:

在三个选项中,我肯定会排除 1 (SortedDictionary),因为 3(数组或 List)根据您的要求(快速查找、排序、按顺序提供的项目,未修改)优于它。

对已排序的数组执行二分查找需要 O(lg n) 时间。根据documentationSortedDictionary 中的查找也需要 O(lg n) 时间,所以使用它没有优势。

由于您获得的数据已经排序,因此该数组的填充时间为 O(n)。 SortedDictionary 中的插入在 O(lg n) 中运行,因此填充它在 O(n * lg n) 中运行,这更糟。

枚举在 O(n) 时间内运行。

为了回答您的问题,我认为 2 和 3 都是可行的选择。哪一个最好取决于您将获得的插入/查找/枚举的比例。

例如,如果您每次枚举进行 10 亿次查找,那么使用 Dictionary 可能会得到回报。如果枚举发生得更频繁,排序后的数组最终可能会更好,因为Dictionary 中的数据首先必须进行排序,而像 QuickSort 这样的算法可以在 O(n * log n) 时间内完成。

我建议您在您的应用程序的典型使用场景中尝试这两种方法,看看哪个最好。

或者,如果内存不是问题,为什么不使用Dictionary 和排序数组?如果做得好,您可以两全其美。

【讨论】:

  • 与使用数组相比,排除SortedDictionary 的优点。我想知道是否可以实现自己的集合,其行为类似于OrderedDictionary。尽管如此,鉴于我只有大约 100 件商品,是否值得付出努力?
  • 可能不会,但如果你想尝试一些简单的事情,只需将字典和数组包装在一起即可。
  • 我把字典和数组包装在一起的理解是:直接查找转发到字典,枚举是通过迭代数组和查找对应的元素来完成的。此外,在插入每个键时,都会将每个键添加到数组和字典中,以使其保持自然顺序(序列)。对吗?
  • 是的,这就是我的想法。当然,刷新时,你必须同时填充数组和字典,但这似乎不是最频繁的操作,所以应该没问题。
猜你喜欢
  • 2014-07-24
  • 2019-03-11
  • 2019-02-07
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多