固定大小的集合,保留顶级(N)值

时间:2010-08-20 15:53:17

标签: c# arrays algorithm sorting collections

我的代码处理了大量的值,我正在寻找一个有效的结构来跟踪顶部(N)值,其中N小于10,所以收集所有数字然后对列表进行排序并取第一个(N)可能不是最有效的方式。

为此,我正在构建一个固定大小为N的集合,以保持顶级(N)值按降序排序。如果value高于任何现有值(在这种情况下删除了最后一个元素)或者集合未满,则排序集合的Add(T value)方法会将值添加到集合中。

我能够使用双倍LinkedList<T>来实现我想要的,因为它具有快速插入和删除功能,但我想知道使用SortedDictionary<TKey, TValue>或优先级队列会更好吗?

谢谢。

8 个答案:

答案 0 :(得分:6)

我只想使用深度有限的堆。我不知道是否已经存在一个库,但它应该很容易实现。

答案 1 :(得分:4)

使用SortedDictionary或SortedList的主要优点是,您可以跳过排序智能,因为它们会为您处理它(例如,您每次添加值时都必须删除第(n + 1)个元素)。 但另一方面,对于10种元素采用那种复杂的结构类似于使用核武杀死苍蝇......

也许链表是一个好方法,而且按顺序插入值的简单线性比较也不比二进制搜索慢(我们仍然谈到针对~3的最大10次比较,当前CPU没有事件感觉差异)

修改

固定数组可用于build prioriry queues with binary heaps,这可能是实现此

的正确方法

答案 2 :(得分:3)

对于这么小的数字,只需保留一个数组。扫描阵列,跟踪最小值及其位置。如果您的新号码大于集合中的最小号码,请将其替换。您当然应该在插入数字后扫描一次最低值,然后只需将新数字与数字进行比较,只有在有更大的数据时才采取措施(替换并重新扫描)。

答案 3 :(得分:3)

表现可能真的改变了。

对于N&lt; 10任何过于复杂的数据结构都可能会显着拖累性能(尽管可能不是灾难性的)所以我会使用数组来存储项目。

然后,如何安排数组中的项目有三种主要可能性:

  1. 排序可能是保持简单的最佳选择:
    • 确定是否插入新项目的恒定时间(与最低项目进行比较)
    • O(N)时间插入 - 但这只发生在N最好的项目中。 如果您的输入足够随机,平均时间会更低,因为大多数插入只会移动顶部底部的一些元素。
  2. 未排序:
    • 每个输入元素的O(N)时间,与“已排序”
    • 相比太多了
  3. 实现优先级队列的二进制堆:实现起来更复杂但可能比“已排序”更快
    • 确定是否插入新项目的恒定时间(与最低项目进行比较)
    • O(log N)要插入的时间 - 这只适用于N个最好的项目

答案 4 :(得分:2)

除非你有充分的理由不这样做,否则我会使用优先级队列。

有一个技巧可以简化逻辑。大多数人的第一个想法是查看每个传入的项目,如果集合包含的项目少于所需的项目,或者新项目大于集合中当前最小的项目,则将其插入集合中。

如果你为集合中的一个额外项目留出空间,你可以简化一些事情。 始终将每个传入的项目插入到集合中,然后如果集合太大,则删除最小的项目。

虽然优先级队列可以说只有10个项目有点过分,但它保持逻辑简单,并且在空间和时间方面都很有效,所以如果你需要N = 10000(或其他),它仍然可以很好地工作

答案 5 :(得分:1)

编辑:

如果只需要前N个值而其他N值没有任何意义,那么普通的旧数组将以低成本完成工作。

保持排序并对抗最大的。只有如果需要存储,请正确插入并移动剩余的元素。小尺寸这是一个便宜的操作,我的猜测是不会经常做。

答案 6 :(得分:1)

如果您的修复大小为10,为什么不简单地使用长度为10且二进制搜索的排序数组?但是我不确定在这个规模上,二进制搜索是不是因为一些开销而在阵列上进行愚蠢搜索的巨大胜利。

答案 7 :(得分:0)

对原始数组使用二进制插入排序,将最小值推到最后。这通常是用于维护小型排序数组的最快方法,例如,通常用作各种排序算法(例如MergeSort)的特殊情况。