【问题标题】:Sorting and merging two arrays in efficient way?以有效的方式对两个数组进行排序和合并?
【发布时间】:2013-04-23 11:45:12
【问题描述】:

我们有两个数组(未排序),容量分别为 nn+m。第一个数组有 n 个元素。第二个数组有 m 个元素(另外还有 n 个位置为更多元素保留)。

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

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

【问题讨论】:

  • 如果这是家庭作业,那很好,但你应该这么说。到目前为止,您尝试过什么?
  • 第二个数组的大小是多少? nn+m 到目前为止,您尝试过什么?
  • @Thrustmaster 尺寸 n+m,包含 m 个元素。
  • 使用快速排序对我的两个数组进行排序,然后使用 MergeSort 合并
  • @brimborium 是的。但这并不意味着承认这个问题是家庭作业以获取更完整/解释性的答案不是一个好习惯meta.stackexchange.com/questions/10811/…

标签: arrays algorithm sorting data-structures


【解决方案1】:

您可以探索归并排序。

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

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

我会使用mergesort,它基本上是通过单独对每个数组进行排序,然后将它们按顺序放在一起

您正在查看合并排序的 O(nlogn) 和快速排序的 O(nlogn),但快速排序的最坏情况可能是 O(n^2)。

【讨论】:

  • 合并排序也可以作为一种稳定的算法来实现,这样您就可以保持相对顺序。快速排序不会这样做
  • 合并排序需要 O(n) 额外空间
  • 然后使用快速排序。或者使用 AVL 树作为数据结构并进行中缀打印 (O(n)) 排序
  • 只是为了澄清一些事情,“合并”这个词与算法内部的工作方式有关,它与接收2个列表并按照问题描述的排序合并它们无关
【解决方案2】:

显然最好的做法是将N的内容复制到N+M数组的空闲空间中,然后对N+M数组进行快速排序。

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

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

那么为什么要将两个起始数组分开?

【讨论】:

  • +1,因为它更加直接和轻松。虽然,既然是作业,可能不是正在寻找的东西,但似乎这是一般应该做的事情。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    如果您存储在第二个数组中,那么您将使用额外的空间,但您可以通过像这样帮助 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) {
    

    【讨论】:

      【解决方案5】:

      我们将较小的数组称为 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 数组的末尾可确保不会发生空间冲突,因此根据您的规范,您不需要额外的侧存储。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-17
        • 1970-01-01
        • 2012-04-12
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 2016-07-26
        相关资源
        最近更新 更多