如何在c中对大量数据进行排序?

时间:2010-11-16 19:33:36

标签: c sorting quicksort

目前我正在尝试将大量数据写入文件,

基本上我生成一个新的数据结构并将其写入文件,直到文件变为1gb大,这发生在6个文件中,每个1gb,结构很小。 8个字节长,两个2变量id和amount

当我生成我的数据时,会按照金额的顺序创建结构并将其写入文件。 但我需要按id排序数据。

记得有6gb的数据,我怎么能用id值对这些结构进行排序然后写入文件?

或者我应该首先写入文件,然后对每个单独的文件进行排序,以及如何将所有这些数据合并到一个文件中?

我有点卡住,因为我想把它放在一个数组中,但很明显这个数据量太大了。

我需要一个很好的方法来排序很多数据? (6GB)

8 个答案:

答案 0 :(得分:5)

我没有找到一个关于此的真正基本答案的问题,所以这里有。

顺便提一下,如果您使用的是64位计算机,则应认真考虑将所有数据写入文件,映射文件的内存,并使用您喜欢的任何数组排序。 Quicksort非常适合缓存:它不会严重破坏。该作业可能旨在阻止您这样做,但可能有点过时; - )

如果做不到这一点,你需要某种外部排序。还有其他方法可以做到,但我认为合并排序可能是最简单的。在开始合并之前:

  • 计算出你可以在内存中放入多少数据(或者再次,mmap)。如果你在PC上,那么1GB似乎是一个公平的假设,但可能会多或少几倍。
  • 加载这么多数据(例如,你的6个文件中的一个)
  • 快速排序(因为你标记了“quicksort”,我猜你知道该怎么做),或者你选择的任何其他类型。
  • 将其写回磁盘(如果你没有mmap)。

这将为您留下6个1GB文件,每个文件都单独排序。此时,您可以逐步进行操作,也可以一次性完成所有操作。有6个块,整个很好,在所谓的“6路合并”:

  • 打开文件进行编写
  • 打开您的6个文件进行阅读,并阅读每个
  • 中的几百万条记录
  • 检查6个缓冲区中每个缓冲区的6个记录。其中一个6必须是最小的。将此内容写入输出,然后向前一步通过该缓冲区。
  • 当您到达每个缓冲区的末尾时,请将其从正确的文件中重新填充。

关于如何计算出6种可能性中最小的可能性,您可以做一些优化,但性能差异很大,以确保使用足够大的读写缓冲区。

显然,合并是6路没什么特别的。如果你宁愿坚持双向合并,这更容易编码,那么你当然可以。它将需要5个双向合并来合并6个文件。

答案 1 :(得分:4)

我推荐这个工具,它是一个轻量级的数据库,在内存中运行,占用的内存非常少。它将保存您的信息,您可以查询它以检索您的信息。

http://www.sqlite.org/features.html

答案 2 :(得分:1)

我建议你不要。

如果您要保存这么多数据,为什么不使用可以拥有许多不同索引和强大请求引擎的专用数据库格式。

但是如果您仍然想使用旧式的fixed-endian结构,那么我建议将数据分成更小的文件,对每个文件进行排序,然后合并它们。一个好的合并算法在nlog(q)中运行。还要确保为您的文件选择正确的算法。

答案 3 :(得分:0)

执行此操作的最简单方法(开发时间)是根据数据将数据写入单独的文件。您不必在文件数和ID数之间匹配1到1(如果有很多ID),但是如果您选择ID的前缀(那么如果某个特定的密钥)记录是987它可能在9文件中,而密钥456的记录将在4文件中)你不必担心在所有文件中找到所有密钥,因为自己对每个文件进行排序会导致然后按顺序查看文件(按名称)会给你排序的结果。

如果那是不可能或不容易的,你需要进行某种类型的外部排序。由于数据仍然分布在几个文件中,这有点痛苦。最简单的事情(按开发时间)是首先独立地对每个单独的文件进行排序,然后将它们合并到一组按ID排序的新文件中。如果您不知道我在说什么,请查找合并 排序。在这一步,你几乎从合并排序开始。

对于太大而无法放入RAM的文件内容进行排序,您可以直接在文件上使用合并排序,也可以使用替换 选择 排序以对文件进行排序。这包括对文件进行多次传递,同时使用一些RAM(越多越好)来保存优先级队列(二进制堆)和一组在此次运行中可能没有任何用处的记录(它们的键表明它们应该在文件中比当前运行位置更早,所以你只是坚持它们直到下一次运行。)

搜索替换 选择 排序锦标赛 排序将会产生更好的解释

答案 4 :(得分:0)

首先,单独对每个文件进行排序。将整个内容加载到内存中,或者(更好)mmap加载它,并使用qsort函数。

然后,编写您自己的合并排序,其中N FILE *输入(例如N=6)并输出到N个新文件,切换到下一个每当一个人填满。

答案 5 :(得分:0)

结帐external sort。找到任何外部mergesort库并根据您的需要进行修改。

答案 6 :(得分:0)

好吧 - 因为实际的分配是保留编码数据,然后将其与解码数据进行比较,我还会说 - 使用数据库并在ID列上创建一个哈希索引。

但是关于这种数字,另一个非常重要的事情是并行执行。有很多方法可以做到这一点。 Steve Jessop提到了一种排序合并方法,很容易并行排序前6个块,唯一的问题是你的机器上有多少cpu内核和内存。 (现在很难找到一台只有1个核心的计算机,而且4GB内存也不是很少见。)

答案 7 :(得分:-1)

也许您可以使用mmap并将其用作可以使用qsort排序的大型数组。我不确定会有什么影响。它会在记忆中成长吗?