我应该使用什么集合来组合最快的密钥检索,以及 c# 中最快的排序枚举?

What collection should I use for combining fastest key retrieval, but also fastest sorted enumeration in c#?

有人可以向我推荐一些用于存储键值对的 C# 集合(或者提示我如何自己实现它),其中我将始终最多拥有 50 个这样的键值对。但通常只有 5-20 个键值对。而且我需要以绝对最快的速度检索给定键的值。首先我想到了 Dictionary,因为它的检索访问时间为 O(1)。但是我仍然不确定对这么小的集合使用字典的开销。但我想即使对于像这样的小型集合,Dictionary 也能提供最快的速度?

然后我还有另一个要求,我需要能够告诉给定键的下一个更大的键(例如,我有值为 2、4、6、8、10、11、12、15 和当我说让我们说 7 时,我需要能够快速分辨出下一个比 7 更大的键是 8)。所以我想到了把这些key集合起来排序,这样我就可以快速分出下一个更大的key)。当时我考虑过使用 SortedDictionary,但我发现,它的访问速度较慢 O(log(n)),但会为我提供找到下一个更大键的另一个好处。

顺便说一句,在整个使用过程中,这个集合永远不会被修改,它只需要在开始时构建,这可能会很慢,构建速度对我来说无关紧要它。我也根本不关心内存使用情况。

例如,我的解决方案也可以结合 Dictionary 和 SortedList。这将是 2 个集合的组合,只是为了最大限度地提高检索速度和“getNextBiggerKey”速度。

或者现在我也在考虑将 nextBiggerKey 存储在该键值对的值中。所以至少对于那些已经在集合中的密钥,它会给我下一个更大的密钥。

请问有没有人有什么好主意,如何在这种情况下完全最大化性能?

更新:我所说的键实际上是分数类型的。但是对于低值,分子和分母都不会大于 256,因此字节应该(很有可能)对它们都足够。

非常感谢您的帮助,我们将不胜感激:)

如果键实际上是一个整数,如您所示,则计算哈希来搜索元素没有任何优势(因此不需要对键进行哈希处理的集合)。由于您可以构建一次列表,然后就可以使用不可变列表,所以我认为二进制搜索是最快的。

我首先要尝试的是正常的 List<T> 键值对,用项目填充它,排序一次,然后使用 List.BinarySearch() 搜索元素。可以肯定的是,您应该对多个场景进行基准测试,但这无疑是一个好的开始。

此答案假设可能的密钥范围很小(最多几千个)。在这种情况下,您可以实施基于 lookup table 的解决方案。假设小数键的范围在 10 到 14 之间,包括二分之一和四分之一。还假设您在此范围内有 4 个键,值分别为 10、10 3/4、12 1/2 和 13。首先,您需要一种方法将键转换为将用作索引的整数数组。在这种情况下,翻译功能将是:

f(x) = (x - 10) * 4

因此键 10 被转换为索引 0,键 14 被转换为索引 16。接下来您需要构造一个长度为 17(从 0 到 16)的数组。下面的 table 显示了这个数组的值:

|   Key   | Translated |  Index  |  Value  |
|---------|------------|---------|---------|
| 10      | 0          | 0       | 0       |
| 10 1/4  | 1          | 1       | 3       |
| 10 1/2  | 2          | 2       | 3       |
| 10 3/4  | 3          | 3       | 3       |
| 11      | 4          | 4       | 10      |
| 11 1/4  | 5          | 5       | 10      |
| 11 1/2  | 6          | 6       | 10      |
| 11 3/4  | 7          | 7       | 10      |
| 12      | 8          | 8       | 10      |
| 12 1/4  | 9          | 9       | 10      |
| 12 1/2  | 10         | 10      | 10      |
| 12 3/4  | 11         | 11      | 12      |
| 13      | 12         | 12      | 12      |
| 13 1/4  | 13         | 13      | -1      |
| 13 1/2  | 14         | 14      | -1      |
| 13 3/4  | 15         | 15      | -1      |
| 14      | 16         | 16      | -1      |

不,让我们使用这个数组进行一些搜索。

  1. 密钥12存在吗?我们应用翻译函数 (12 - 10) * 4 并得到索引 8。array[8] 的值是 10。10 不同于 8,所以密钥12不存在。
  2. 键 10 3/4 的下一个更大的键是什么?我们应用翻译函数并得到索引 3。array[3] 是 3,所以密钥存在,但我们对此不感兴趣。我们需要查看下一个数组元素 array[4]。它的值为 10,是密钥 12 1/4 的翻译。所以 10 3/4 的下一个更大的键是 12 1/4。

现在您已经有了按键搜索此结构的方法,您可以考虑如何将每个键与一个值相关联,以最终得到一个合适的字典。最简单的方法可能是在混合中添加另一个数组,长度相等,将每个键的值存储在同一索引中。