我有一个非常庞大的元素列表(数十万)。
我有一个过滤器,可以接受或者拒绝元素。
我想要获得符合过滤器条件的前100个元素。
目前,我的做法是先对结果进行排序,然后再取前100个符合条件的元素。 这样做的原因是过滤器不是完全快速的。
但现在,排序步骤比筛选步骤花费更长时间,所以我想以某种方式将它们结合起来。
是否有一种算法可以将排序/过滤的考虑因素结合起来,以获取前100个符合过滤器条件的结果,而不需要排序所有元素的成本呢?
我有一个非常庞大的元素列表(数十万)。
我有一个过滤器,可以接受或者拒绝元素。
我想要获得符合过滤器条件的前100个元素。
目前,我的做法是先对结果进行排序,然后再取前100个符合条件的元素。 这样做的原因是过滤器不是完全快速的。
但现在,排序步骤比筛选步骤花费更长时间,所以我想以某种方式将它们结合起来。
是否有一种算法可以将排序/过滤的考虑因素结合起来,以获取前100个符合过滤器条件的结果,而不需要排序所有元素的成本呢?
我的直觉是从列表中选择前100个元素(比排序便宜得多,使用您喜欢的QuickSelect变体)。将这些元素通过过滤器,产生n
个成功和100-n
个失败。如果n < 100
,则从余下列表的顶部选择100-n
个元素并重复此过程:
k = 100
while (k > 0):
select top k from list and remove them
filter them, yielding n successes
k = k - n
p
不是表示元素通过过滤器的概率吗?也就是说,如果过滤器接受大部分元素,则我们应该要求更少的过滤器运用,而不是更多。 - Steve Jessop我曾通过使用二叉树进行排序,并在插入过程中保持当前节点左侧元素的计数来解决这个确切的问题。有关详细信息,请参见http://pub.uni-bielefeld.de/publication/2305936(图4.4等)。
如果我理解正确,你有两个选择:
选择100个元素-进行N次过滤检查操作,然后进行100(lg 100)次排序。
排序然后选择100个元素-至少需要N(lg N)次排序,然后再进行选择。
第一种方法听起来似乎比先排序再选择更短。
我会先进行筛选,然后将筛选结果插入到优先队列中。跟踪优先队列中的项目数量,在插入之后,如果它大于你想保留的数量(在你的情况下是100个),则弹出最小的项目并丢弃它。
史蒂夫建议使用快速排序是一个好主意。
1 读取前1000个元素。
2 对它们进行排序并选择第100个最大的元素。
3 在整个文件上运行一次快速排序,以步骤2中的元素作为枢轴。
4 选择快速排序通过结果的上半部分进行进一步处理。
您保证在单次快速排序的上半部分至少有100个元素。假设前1000个元素相当代表整个文件,则在步骤4中应该得到原始元素的约十分之一。