Algorithm 如何将数据添加到一组已排序的文件中
我很抱歉,如果这已经被重复,但我找不到任何与我选择的措辞帖子。我正在准备面试,我一直在阅读外部排序。例如,如果要对多个32位整数的硬盘进行排序,可以进行计数排序,并使用64位计数器对32位整数进行计数。然后,在每个可能的32位整数值处,都有一个表示它的计数器。您还可以对类似的事情使用外部合并排序,使用O(nlogn)时间而不是O(1)时间。然而,我一直在考虑一种可能非常常见的情况,但我想不出最好的方法——将新数据添加到可能跨越多个硬盘的一组排序文件中Algorithm 如何将数据添加到一组已排序的文件中,algorithm,sorting,external-sorting,Algorithm,Sorting,External Sorting,我很抱歉,如果这已经被重复,但我找不到任何与我选择的措辞帖子。我正在准备面试,我一直在阅读外部排序。例如,如果要对多个32位整数的硬盘进行排序,可以进行计数排序,并使用64位计数器对32位整数进行计数。然后,在每个可能的32位整数值处,都有一个表示它的计数器。您还可以对类似的事情使用外部合并排序,使用O(nlogn)时间而不是O(1)时间。然而,我一直在考虑一种可能非常常见的情况,但我想不出最好的方法——将新数据添加到可能跨越多个硬盘的一组排序文件中 如果内存中有数据,可以使用堆(优先级队列)在
如果内存中有数据,可以使用堆(优先级队列)在logn时间内完成此插入。然而,我们不能从硬盘空间堆。对于列表,您必须使用O(logn)搜索来查找数据的位置(对于二进制搜索,排序),然后向后或向前移动其余数据,或者根据容器的实现(数组、链接列表等),您可能不必移动任何内容。然而,在硬盘世界中,读写比RAM要昂贵得多,因此在某个地方插入数据,然后转移(重写)其余的数据似乎昂贵得令人望而却步。有什么技巧可以推荐给我吗?我很乐意阅读自己的文章,我只是找不到正确的方式来表达我的问题以找到任何信息。谢谢大家! 如果你在这里(或其他地方)查找“外部排序”,你会发现关于你所描述内容的讨论。外部排序在这里也是一个标记 然而,在硬盘世界中,读和写要多得多 比在RAM中更昂贵,所以在某处插入数据然后移动 (重写)其余的数据似乎过于昂贵
外部排序适用于内存不足(或大多数情况下“每个进程”内存不足)的情况。数据集太大而无法立即保存在内存中的情况并不少见。因此,您接受I/O绑定排序的更高运行时成本。如果您在此处(或其他地方)查找“外部排序”,您将发现您所描述内容的讨论。外部排序在这里也是一个标记 然而,在硬盘世界中,读和写要多得多 比在RAM中更昂贵,所以在某处插入数据然后移动 (重写)其余的数据似乎过于昂贵
外部排序适用于内存不足(或大多数情况下“每个进程”内存不足)的情况。数据集太大而无法立即保存在内存中的情况并不少见。因此,您接受较高的I/O绑定排序的运行时成本。我要说的是,读取已排序数据的文件,读取要排序并添加到其中的文件,扣上计数器并用新计算的数据文件覆盖已排序的数据文件。在现代磁盘系统上,直接读取的成本比随机读取低很多,而且无论怎样,您都需要为找到的每一个int指定一个位置,因此,对整个卷进行单次顺序读取比对每个要排序的文件进行32次单扇区读取所需的时间要少
另外,我想说排序32位整数最好是以计数器的形式完成,特别是在超大规模的情况下,如“几个硬盘”,在32位空间中,几乎每个存储桶中至少有1个,因此,存储64位*2^32可能比2^33 32位零和2^32位一小,然后…我会说,读取已排序数据的文件,读取要排序并添加到其中的文件,扣上计数器并用新计算的数据覆盖已排序的数据文件。在现代磁盘系统上,直接读取的成本比随机读取低很多,而且无论怎样,您都需要为找到的每一个int指定一个位置,因此,对整个卷进行单次顺序读取比对每个要排序的文件进行32次单扇区读取所需的时间要少
另外,我想说排序32位整数最好是以计数器的形式完成,特别是在超大规模的情况下,如“几个硬盘”,在32位空间中,几乎每个存储桶中至少有1个,因此,存储64位*2^32可能比2^33 32位零和2^32位一小,然后…如果内存中有空间保存文件,并且有一组最小元素为k的数字,则必须重新写入文件中大于k的所有数字。这是没有办法的。他们都必须至少换一个位置 如果您希望利用数组的大部分已经排序的事实,并且内存中有足够的空间进行排序,那么对插入的元素进行排序并将其与大于其最小成员的元素列表合并是一种很好的快速方法。例如: 磁盘: 123456810112 插入:9713 对插入进行排序: 7 9 13 在磁盘上查找适用的已排序列表的子集: 8101112 合并中的元素(如合并排序:) 7 8 9 10 11 12 13 将它们复制回磁盘: 123456789101113 另一方面,如果您的内存空间远远小于列表的总大小,则建议使用其他技术。例如: 1234。。1000 1002 1003... 999981000000 作为磁盘上的列表和 1001999999 作为你的插入物。在这种情况下,您需要遍历每个元素,计算插入列表中小于该元素的元素数,然后执行此操作。在这个简单的例子中,naive计数器非常快——您可以看到10000000需要两次跳转。如果号码是