以有效的方式排序和合并两个数组?

时间:2013-04-23 11:45:12

标签: arrays algorithm sorting data-structures

我们有两个数组(未分类),容量 n n + m 。第一个数组有 n 元素。第二个数组具有 m 元素(以及为更多元素保留的 n 位置)。

目标是合并两个数组并以排序的方式将结果存储在第二个数组中,而不使用额外的空间。

目前,我使用快速排序对两个数组进行排序,然后使用merge-sort合并它们。有没有更有效的方法来实现这个???

5 个答案:

答案 0 :(得分:2)

您可以探索合并排序。

https://www.google.com/search?q=mergesort&ie=UTF-8&oe=UTF-8&hl=en&client=safari#itp=open0

或者根据大小,您可以对每个数组执行快速排序,然后使用合并排序技术(或合并,然后快速排序)合并它们。

我会选择mergesort,它基本上是通过单独排序每个数组,然后按顺序将它们组合在一起

你正在寻找关于mergesort的O(nlogn)和关于quicksort的O(nlogn),但是对于quicksort可能是O(n ^ 2)最坏的情况。

答案 1 :(得分:2)

显然,最好的办法是将N的内容复制到N + M阵列的自由空间中,并快速分配N + M阵列。

通过执行2个快速排序然后进行合并排序,您只会降低整个操作的效率。

这是一个心理练习,如果你必须对长度为M的数组进行排序,你会将它分成2个数组,M1和M2,对每个数组进行排序,然后将它们合并排序在一起吗?不会。如果您这样做,您只会限制每次快速排序电话的可用信息,从而减慢过程。

那么为什么要将两个起始阵列分开?

答案 2 :(得分:0)

如果您要存储在第二个阵列中,而不是使用额外的空间,但可以通过像这样帮助GC来最小化:

  • 在第二个数组中连接两个数组
  • 将之前的两个变量都设置为null,以便它们有资格进行垃圾回收
  • 排序第二个数组Arrays.sort(...) - O(n log(n))

查看此方法的javadoc:

/**
  * Sorts the specified array into ascending numerical order.
  *
  * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
  * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
  * offers O(n log(n)) performance on many data sets that cause other
  * quicksorts to degrade to quadratic performance, and is typically
  * faster than traditional (one-pivot) Quicksort implementations.
  *
  * @param a the array to be sorted
  */
  public static void sort(int[] a) {

答案 3 :(得分:0)

如果我还想保证O(n * log(n))行为,我会使用Heapsort的修改版本,它将使用这两个数组作为堆的基础,并将存储排序数据在数组的附加部分。

这也可能比两个Quicksorts更快,因为它不需要额外的合并操作。当小数组被排序时,Quicksort也非常慢(问题的大小没有提到问题的设置)。

答案 4 :(得分:0)

让我们将较小的数组称为N数组,将另一个数组称为M数组。我假设M阵列的元素最初位于0到m-1的位置。使用您喜欢的技术对两个阵列进行排序,这可能取决于其他标准,例如稳定性或限制最坏情况的行为。

if min(N) > max(M)
   copy N's elements over starting at location m [O(n) time]   
else
   move M's elements to the end of the M array (last down to first) [O(m) time]   
   if min(M) > max(N)
      copy N's elements over starting at location 0 [O(n) time for the copy]
   else
      perform classic merge: min of remaining m's and n's gets migrated
      to next available space in M [O(min(m,n) time]

总的来说,这是由初始排序时间决定的,合并阶段都是线性的。将m移动到M阵列的末尾可确保没有空间冲突,因此您不需要根据规范进行额外的侧面存储。