【问题标题】:merge sort with large number of integers具有大量整数的合并排序
【发布时间】:2015-10-08 13:17:50
【问题描述】:

需要对大量无法保存到内存中的整数进行排序。想知道合并排序是否是正确的方法?我的解决方案是这样的,

  1. 对每 5% 的整数使用基于内存的排序,这可以保存在内存中,使用在内存中高效执行的快速排序;
  2. 每20个块排序后,使用归并排序对20个列表进行排序,对于归并排序,我只需要将每个文件的一部分加载到内存中,如果当前部分在同一列表中,则加载同一列表的下一部分完全排序为最终结果。由于 20 个列表中的每一个都是排序的,我只需要从头到尾顺序加载部分块,因此内存是负担得起的。

我不确定这是否是大量整数排序的正确方法?

【问题讨论】:

  • 可能需要研究的是外部排序en.wikipedia.org/wiki/External_sorting
  • 是的,这是正确的方法。我已经用过很多次了。除了我多次进行 2 路合并,而不是 20 路合并。
  • 是的,你描述的正是外部归并排序算法。
  • 我不确定 20-way 是否会更快。您对数据的传递次数较少,但比较过程要复杂得多。鉴于您收到的答案,我猜有人已经对此进行了研究并确定 16 路是最佳的,但我无法确认。
  • 它们是什么整数?常规 32 位整数?

标签: algorithm sorting


【解决方案1】:

因为,

都是整数,大部分是1-100

您只需要Counting Sort


实现起来非常简单。

  1. 创建一个包含 100 个整数(或 HashMap<int, int>)的数组,名为 intCounts(如果您认为 32 位会溢出,请使用 64 位整数)
  2. 一一读取你要排序的整数
  3. 对于每个要排序的inputInteger,只需执行intCounts[inputInteger]++
  4. 读完所有整数后,intCounts[i] 会告诉您在大量整数中看到整数 i 的次数
  5. 只需遍历您的 intCounts 从最低索引到最高索引
  6. 回信iintCounts[i]
  7. 您现在已经写回了所有输入整数的排序列表。

【讨论】:

  • displayName,聪明又聪明。 :)
  • @LinMa:这没什么好说的。我只是被告知。现在,你也是。
  • 希望您能随时帮助通知我。喜欢向你学习。 :)
【解决方案2】:

GNU 排序程序(与其 Unix 前身一样)使用内存中排序,然后根据需要进行尽可能多的 16 路合并。请参阅此处的代码以了解更多信息:

http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/sort.c#n306

【讨论】:

  • 感谢cliffordheath,对于 16 路合并,他们是否使用基于外部存储的合并排序?
  • 16 路或任何 k 路排序通常是归并排序,在这种情况下是外部归并排序。 wiki article - external sort.
  • @LinMa - 取决于是否通过增大 k 来减少合并通道的数量。一旦你有可以处理 k 路合并的代码,更大的 k 不会使它更复杂,但即使是基本的 k 路合并也很复杂,因为当到达运行结束时,它是 k-1方式合并,然后是 k-2 方式合并,然后只剩下一次运行的剩余部分,即被复制。要使 k > 2 有效,需要大量 I/O 来减少随机访问开销(假设您没有 2 x k 设备或使用 SSD 驱动器进行排序)。
  • @Lin:我指出了代码,以便您阅读!是的,他们使用临时文件。每个 N 路合并排序产生 1 个文件 - 因此,如果您有 M 个文件开始,则所需的合并次数按照 log-to-base-N(M) 的顺序排列。所以N越大,合并的次数越少
  • @LinMa - 跟进cliffordheath 的评论,示例代码的初始阶段创建了M 个临时排序文件,其中M =(文件大小)/(有效缓冲区大小)。使用单个文件和 M 文件指针将是另一种选择,但我的猜测是在编写示例时,文件指针是 32 位的。 Linux 和 Windows 现在都有 fseek() 和 ftell() 的 64 位替代方案。
猜你喜欢
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 2020-07-31
  • 1970-01-01
  • 2016-12-28
相关资源
最近更新 更多