磁盘搜索/排序算法

时间:2010-03-30 03:39:32

标签: algorithm sorting search

如果数字范围为1到10,000,则输入是随机顺序。 约束: 在任何时候,只能将1000个数字加载到内存中。

假设: 假设唯一的数字。

我提出以下有效的“When-Required-sort算法”。

我们将数字写入指定为包含特定数字范围的文件中。例如,File1将具有0 - 999,File2将具有1000 - 1999,依此类推。

如果正在搜索特定数字,即“2535”,那么我们知道该数字在文件3中(在范围内进行二进制搜索以查找文件)。然后将file3加载到内存并使用说快速排序(在数组大小较小时优化添加插入排序)进行排序,然后使用二进制搜索搜索此排序数组中的数字。当搜索完成后,我们会回写已排序的文件。

因此,从长远来看,所有数字都将被排序。

请对此提案发表评论。

5 个答案:

答案 0 :(得分:6)

它被称为Bucket sort

主内存有限时的另一种方法是使用Merge sort

根据需要对每个桶进行排序的设计部分可能更好地描述为“按需”,“及时”或“懒惰”。人们已经熟悉了重用命名法,而不是发明“何时需要排序”一词。

您是否考虑过如何处理其他输入?如果某些存储桶已经排序,然后添加更多数字,会发生什么?

我假设最终目标是确定数字是否包含在集合中,而不是生成排序列表。如果经常这样做,则对分拣桶的初始开销有好处。如果不经常,对适当的桶进行线性扫描就足够了。

另一种选择。存储桶排序可以被认为是一个简单的哈希表。哈希函数是n/1000。由于每个桶中可能存在大量值(最多1000个),因此预计会发生冲突。您可以使用更复杂的哈希并获得O(1)搜索性能,而不是使用按需排序(然后使用二进制搜索)来解决冲突。

答案 1 :(得分:3)

每个数字可以是1到10000.这意味着每个数字至少占14位(2 13 = 8192,2 14 = 16384)。

您可以将1000个数字加载到内存中。这意味着您可以使用位掩码,因为您已声明数字是唯一的。设置一个10000位的位掩码,每个位数为14位,只有715个数字(如果每个数字的位数超过14位,则最多为少)。

最初清除位以指示不存在数字,然后一次读取一个数字,设置相关位以指示它存在。这是O(n)操作。

然后,一旦你设置了这个位数组,它就是一个O(1)操作,看看是否设置了一个特定的位。

即使最佳排序算法也不会比随机数据上的O(n)更好。

答案 2 :(得分:1)

上一张海报的描述是正确的 - 这是一个桶排序。

一些密切相关的种类是Radix种类。这些是O(1),但取决于范围内相当均匀的值分布。

答案 3 :(得分:0)

使用mergesort:
http://en.wikipedia.org/wiki/Sorting_algorithm

mergesort的内存消耗为n,而bucketsort的内存消耗为n * k 对于bucketsort最坏的情况是n ^ 2 * k,而mergesort是n * ln(n)

请注意:在几乎任何必须对大量数字进行排序的情况下,mergesort是该任务最有效的排序算法。

答案 4 :(得分:0)

我这样读了你的问题 “如果输入来自域D的n个数字,那么记下那些n个数字的排序输入的最快方法是什么,前提是你只能在存储器中存储k个数字(k

请注意,在您的问题中,您说域D的范围是1到10000.我认为这是过于简单化。当n = 10000且输入为范围(无重复)时,这将变为平凡,因为您将确切地知道应在排序文件中写入每个数字的位置。此外,您确切地知道该文件的内容是什么,并且您根本不必编写它而您不必阅读输入。 :d

现在,如果N(D)不等于n或者你允许重复,那么问题会变得更有趣。

如果内存有限,我认为直观的方法就是这样做:

第一种方法

读取输入后,您可以在写入之前对大多数k1元素进行排序,其中k1是需要对内存中的k个元素进行排序的元素数。

你最终会得到内部排序的f =(n div k1)+ 1个文件。

然后你需要从f文件中读取并合并部分排序的数据,将它们写入最终文件。

不同的排序具有不同的内存要求,并将生成不同数量的必须合并的部分排序文件。

合并更多文件需要更多内存,因为您不知道在哪个文件中可以找到下一个数字。

第二种方法

如您所知,另一种方法是知道您可以在哪个文件中找到下一个数字。这就像根据它们的大小将它们放入桶中(通过分类来分配排序),但问题在于,除非您知道如何分发数据,否则确定每个桶的范围并不容易。

对于最少的文件数,每个存储桶的大小应该是k1。

假设您对数据分布有所了解,可以这样做,否则您需要再次传递数据以确定切割点。

对于不知道存储桶大小的一般数据,您不能首先传递所有数据(例如,当输入进入时,您必须为数据保留某种排序结构,并且你不知道接下来会发生什么。你基本上必须保留一个索引,如B +树,但这不是最佳的。索引针对快速检索进行了优化,并且(其中一些)用于插入少量新元素。

第3种方法
拥有这么小的域允许简单地计算数字并将其频率写下来。如果你可以随机访问输出文件,文件系统缓冲可以处理效率(缓冲是一种算法,可以有效地限制内存使用的磁盘写入,唯一的问题是如果缓冲区的大小小于k数如果选择的位图像结构是最有效的。)

直觉上我会说最好的选择是首先计算分布并计算每个桶的大小和限制。然后将文件分成多个桶。然后对每个桶进行排序我想在将数据写入存储桶时至少部分地对数据进行排序可以挤出一些性能。