7

如果给你:

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

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

有人对如何改善这一点有任何建议吗?

4

2 回答 2

12

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

您对快速排序的最坏情况行为的担忧通常无需担心,因为如果您随机选择枢轴,那么您获得非常糟糕的运行时的可能性很低。即使数据已经排序,随机枢轴策略也能很好地工作,因为它没有最坏情况的输入(除非有人知道你的随机数生成器和种子)。您还可以使用类似introsort的快速排序变体,它没有最坏情况的行为,作为您的排序算法,以避免这种最坏情况。

也就是说,由于您知道数据已经部分排序,您可能需要为您的排序步骤研究自适应排序算法。您已经为此提到了插入排序,但是那里有更好的自适应算法。如果内存不足(正如您所描述的),您可能想尝试研究smoothsort算法,它具有最佳情况运行时间 O(n),最坏情况运行时间 O(n log n),并且仅使用 O( 1)记忆。它不像其他一些算法(如 Python 的timsortnatural mergesortCartesian tree sort)那样自适应,但它的内存使用率较低。它也没有一个好的快速排序那么快,但如果数据真的大部分是排序的,它可以做得很好。

希望这可以帮助!

于 2012-02-29T03:49:27.753 回答
1

从表面上看,我会用快速排序分而治之,然后收工。许多算法问题都被过度思考了。

现在,如果您确实有要使用的测试数据并且真的想要掌握它,请在中间放置一个抽象类并进行基准测试。我们可以整天胡思乱想,但知道数据已经部分排序,您必须进行测试。在大多数快速排序实现中,排序数据会带来最坏情况下的性能。

考虑到有许多排序算法,有些更适合排序集。此外,当您知道一个集合已排序时,您可以在 n 时间内将其与另一个集合合并。因此,当您比较添加单个 (n) 通道时,首先识别已排序数据的块可能会为您节省大量时间,并大大减少快速排序进入 (n 2 ) 时间的机会。

于 2012-02-29T03:53:57.327 回答