一个很好的排序算法,适用于大部分排序的数据,并不全部适合内存?

时间:2012-02-29 03:28:12

标签: java algorithm sorting data-structures space-complexity

如果给你:

  • 一定数量的数据
  • 内存大小为数据大小的一半
  • 部分数据已排序
  • 您不知道已排序数据的大小。

您会选择哪种排序算法? 我在插入和快速排序之间进行辩论。我知道插入排序的最佳情况是O(n),但最坏的情况是O(n 2 )。另外,考虑到内存有限的事实,我将数据分成两部分,并在每一部分上快速排序,然后将所有内容合并在一起。对于O(n log n)的净运行时间,需要花费O(n)时间来分割数据,O(n)用于合并数据,O(n log n)用于使用快速排序对数据进行排序。

有没有人对如何改进这方面有任何建议?

2 个答案:

答案 0 :(得分:11)

您的类似mergesort的方法似乎非常合理。更一般地说,这种类型的排序算法称为external sorting algorithm。这些算法通常可以像您所描述的那样工作 - 将一些数据子集加载到内存中,对其进行排序,然后将其写回磁盘。最后,使用合并算法将所有内容合并在一起。加载多少以及使用哪种排序算法的选择通常是主要关注点。我将主要关注排序算法的选择。

您对快速排序的最坏情况行为的担忧一般来说 无需担心,因为如果您随机选择枢轴,那么您获得非常糟糕的运行时间的概率很低。即使数据已经排序,随机数据转换策略也可以正常工作,因为它没有最坏情况输入(除非有人知道您的随机数生成器和种子)。您也可以使用像introsort这样没有最坏情况行为的快速排序变体作为排序算法,以避免出现这种最坏情况。

也就是说,既然您知道数据已经部分排序,您可能需要查看adaptive sorting algorithm的排序步骤。你已经提到了插入排序,但是有更好的自适应算法。如果内存不足(如您所述),您可能需要尝试查看 smoothsort 算法,该算法具有最佳案例运行时O(n),最坏情况运行时O (n log n),仅使用O(1)内存。它不像其他算法那样具有自适应性(如Python的timsortnatural mergesortCartesian tree sort),但它的内存使用率较低。它也不如一个好的快速排序快,但如果数据真的大部分排序,它可以做得很好。

希望这有帮助!

答案 1 :(得分:1)

从表面上看,我会划分&用quicksort征服并称之为一天。许多算法问题都被过度考虑。

现在,如果你确实有测试数据可以使用并且真正想要掌握它,那么在中间和基准测试中粘贴一个抽象类。我们可以整天摆脱困境,但是知道数据已经部分排序,你将不得不进行测试。在大多数快速排序实施中,排序数据会带来最坏情况的性能。

考虑有many sorting algorithms,有些更适合排序集。此外,当您知道某个集合已排序时,您可以在n次将其与另一个集合合并。因此,当您比较添加单个(n)传递并大大降低快速进入(n 2 )时间的机会时,首先识别排序数据的块可能会节省大量时间。